I'm new in RoR, and I'm trying to practice building a web app. I have a classic app with User who have Post.
An other model Online is used to put the post on a common wall, and it's associated with a nested form Orders which represents pieces available.
So now, I'm trying to update that nested form (orders) with a button in my post show view. But it return me an error "No route matches [POST]"
while I write a PUT. So why he thinks that I want to make a new order (POST) ? And how can I change that ?
My code :
routes :
Rails.application.routes.draw do
get 'profiles/show'
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
devise_for :users, :controllers => { registrations: 'registrations' }
resources :posts do
resources :comments
resources :onlines do
resources :orders
end
end
get ':pseudo', to: 'profiles#show', as: :profile
get ':pseudo/edit', to: 'profiles#edit', as: :edit_profile
patch ':pseudo/edit', to: 'profiles#update', as: :update_profile
put 'online/:id/taked', to: 'onlines#taked', as: :taked_online
root 'posts#index'
Views/posts/show :
<div class="col-md-9">
<h3>Orders :</h3>
<div id="Orders">
<ul>
<%- #post.onlines.each do |online| %>
<%- online.orders.each do |order| %>
<%- if order.taked == false %>
<li>
<%= link_to 'Take', taked_online_path(online), method: :update, class: "btn btn-warning"%>
</li>
<%end%>
<%end%>
<%end%>
</ul>
</div>
</div>
and my Online controller :
before_action :set_post
before_action :owned_online, only: [:new, :update]
before_action :set_online, except: [:taked]
before_action :set_unline, only: [:taked]
def new
#online = current_user.onlines.build
#online.post_id = #post.id
#online.user_id = current_user.id
end
def edit
end
def taked
#online.orders.update(taked: true, taked_at: Time.zone.now, taked_by: current_user)
end
def create
if Online.where(post_id: params[:post_id]).any?
#online = Online.where(post_id: params[:post_id]).last.update_attributes(push: false)
end
#online = #post.onlines.create(online_params)
if #online.save
if #online.portion <= 0
#online.update(push: false)
flash[:success] = 'Veuillez indiquer le nombre de parts disponibles '
redirect_to root_path
else
#online.update(pushed_at: Time.zone.now)
#online.update(push: true)
flash[:success] = 'Votre post est en ligne !'
redirect_to root_path
end
else
render 'new'
end
end
def update
if #onlines.update(online_params)
if #online.push == false
if #online.portion <= 0
#online.update(push: false)
flash[:success] = 'Veuillez indiquer le nombre de parts disponibles '
redirect_to root_path
else
#online.update(push: true)
flash[:success] = 'Votre post a bien été pushé !'
redirect_to root_path
end
end
else
#user.errors.full_messages
flash[:error] = #user.errors.full_messages
render :edit
end
end
private
def online_params
params.require(:online).permit(:user_id, :post_id, :prix, :portion, :push, :pushed_at, orders_attributes: [:id, :taked, :taked_at, :taked_by, :validated_at, :validated_by, :_destroy])
end
def owned_online
#post = Post.find(params[:post_id])
unless current_user == #post.user
flash[:alert] = "That post doesn't belong to you!"
redirect_to :back
end
end
def set_post
#post = Post.find_by(params[:post_id])
end
def set_online
#post = Post.find(params[:post_id])
#online = Online.find_by(params[:id])
end
def set_unline
#online = Online.find_by(params[:id])
end
end
Models :
Post :
class Post < ActiveRecord::Base
belongs_to :user
has_many :onlines, dependent: :destroy
scope :push_posts, lambda { joins(:onlines).merge(Online.push) }
has_many :ingredients, dependent: :destroy
accepts_nested_attributes_for :ingredients, reject_if: :all_blank, allow_destroy: true
has_many :comments
validates :image, presence: true
has_attached_file :image, styles: { medium: "300x300#"}, default_url: "/images/:style/missing.png"
validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/
end
Online:
class Online < ActiveRecord::Base
belongs_to :post
belongs_to :user
has_many :orders
accepts_nested_attributes_for :orders, allow_destroy: true
scope :push, ->{ where(push: true).order("pushed_at DESC") }
end
& User :
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :posts, dependent: :destroy
has_many :onlines, dependent: :destroy
has_many :comments
has_many :orders, dependent: :destroy
validates :pseudo, presence: true, length: { minimum: 4, maximum: 16 }
has_attached_file :avatar, styles: { medium: '100x100#' }
validates_attachment_content_type :avatar, content_type: /\Aimage\/.*\Z/
end
Error :
Well, so if you have any advices for that, I'll take it !! Thanks
No route matches [POST]
In your link_to, you have method: :update which is wrong. You need to change it to below
<%= link_to 'Take', taked_online_path(online), method: :put, class: "btn btn-warning"%>
Related
In my blog app, there are posts and each post can optionally have tags. When the user is on the new or edit post form, they currently have the means to select or deselect tags to associate with the post. There is a many-to-many relationship between the post and tag models and I am using bootstrap, bootstrap_form and bootstrap-select. This all works seemingly very well. The problem is, when the user is assigning tags to their post, these tags currently have to already exist (otherwise they would have to abort their post and go add tags...bad user experience). I am trying to devise a way to give the user the option to create new tags and/or select already-existing tags and apply them to the post, all on the same post form in the collection_select field, all at the same time.
Apparently I'm asking the wrong questions on google...wouldn't this be a common need, already solved?
I am asking for guidance in providing an 'add new tag' functionality to an otherwise functional collection_select field. How best to go about this?
Posts Controller:
class PostsController < ApplicationController
before_action :set_post, only: %i[edit update interim destroy]
# GET /posts
# GET /posts.json
def index
if user_signed_in? && current_user.admin_role
if params[:tag]
#posts = Post.tagged_with(params[:tag]).all.order('updated_at DESC').page params[:page]
else
#posts = Post.all.order('updated_at DESC').page params[:page]
end
else
if params[:tag]
#posts = Post.tagged_with(params[:tag]).where(published: true).order('updated_at DESC').page params[:page]
else
#posts = Post.where(published: true).order('updated_at DESC').page params[:page]
end
end
end
# GET /posts/new
def new
#post = current_user.posts.build
#categories = Category.pluck(:name, :id)
end
# GET /posts/1/edit
def edit
#categories = Category.pluck(:name, :id)
#cat = #post.category_id
end
# POST /posts
# POST /posts.json
def create
#post = current_user.posts.create(post_params)
respond_to do |format|
if #post.save
if params[:interim]
format.html { redirect_to edit_post_path(#post), notice: 'Post was successfully created.' }
format.json { redirect_to edit_post_path(#post), status: :created, location: #post, notice: 'Post was successfully created.' }
elsif params[:complete]
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: #post }
end
else
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
respond_to do |format|
if #post.update(post_params)
if params[:interim]
format.html { redirect_to edit_post_path(#post), notice: 'Post was successfully updated.' }
format.json { redirect_to edit_post_path(#post), status: :ok, location: #post, notice: 'Post was successfully updated.' }
elsif params[:complete]
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #post }
end
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_post
#post = Post.find(params[:id])
end
def post_params
params.require(:post).permit(:title, :content, :user_id, :published, :category_id, :tag_list, :tag, { tag_ids: [] }, :tag_ids,
comment_attributes: [:id, :title, :user_id, :content, :post_id, :parent_id, :ancestry, :commentable, :commentable_id, :commentable_type])
end
end
No tags controller (not needed thus far)
Post Model:
class Post < ApplicationRecord
has_many :taggings
has_many :tags, through: :taggings
has_rich_text :content
include PgSearch::Model
multisearchable :against => [:title, :content]
def self.published(post)
post.published
end
def self.tagged_with(name)
Tag.find_by!(name: name).posts
end
def self.tag_counts
Tag.select('tags.*, count(taggings.tag_id) as count').joins(:taggings).group('taggings.tag_id')
end
def tag_list
tags.map(&:name).join(', ')
end
def tag_list=(names)
self.tags = names.split(',').map do |n|
Tag.where(name: n.strip).first_or_create!
end
end
end
Tag Model:
class Tag < ApplicationRecord
has_many :taggings
has_many :posts, through: :taggings
end
Tagging Model:
class Tagging < ApplicationRecord
belongs_to :tag
belongs_to :post
end
Post Form Partial (the actual new and edit views do nothing but render this form):
<%= bootstrap_form_for #post, local: true, html: { class: 'form-horizontal' } do |f| %>
<%= f.text_field :title %>
<%= f.rich_text_area :content, control_class: 'trix-content-edit' %>
<%= f.collection_select :category_id, Category.all, :id, :name %>
<%= f.form_group :published, label: { text: "Publication Status" } do %>
<%= f.radio_button :published, true, label: "Published" %>
<%= f.radio_button :published, false, label: "Draft" %>
<% end %>
<%= f.collection_select :tag_ids, Tag.order(:name), :id, :name, {label: 'Tags', include_blank: true}, {class: 'selectpicker show-tick', multiple: 'multiple', title: 'Make your selection...', 'data-live-search': 'true', 'data-actions-box': 'true'} %>
<br><br>
<%= f.submit "Save and Resume Editing", name: "interim", class: "btn btn-primary" %>
<%= f.submit "Save and Quit", name: "complete", class: "btn btn-primary" %>
<br><br>
<% end %>
No forms for tag at this time.
I created a chatroom feature with Rails 5.1, the issue that I am having, is that I'm unable to destroy the chatrooms created by the current_user. How can I fix my code to destroy the chatroom and the users within the thread by the owner of the chatroom?
chatroom.rb
class Chatroom < ApplicationRecord
has_many :chatroom_users, dependent: :destroy
has_many :users, through: :chatroom_users
has_many :messages, dependent: :destroy
belongs_to :category
validate :max_channel_check, on: :create
validates :category, presence: true
scope :public_channels, ->{ where(direct_message: false) }
scope :direct_messages, ->{ where(direct_message: true) }
scope :recent, -> {where('created_at >= :thirty_minutes_ago', thirty_minutes_ago: Time.now - 30.minutes.ago)}
def max_channel_check
if current_user.chatrooms.count >= 5
errors.add(:base, "You've created the maximum amount of channels, please delete some of the channels you have open.")
end
end
def self.direct_message_for_users(users)
user_ids = users.map(&:id).sort
name = "DM:#{user_ids.join(":")}"
if chatroom = direct_messages.where(name: name).first
chatroom
else
# create a new chatroom
chatroom = new(name: name, direct_message: true)
chatroom.users = users
chatroom.save
chatroom
end
end
end
chatrooms_controller.rb
class ChatroomsController < ApplicationController
before_action :set_chatroom, only: [:show, :edit, :update, :destroy]
include ChatroomsHelper
include UsersHelper
# GET /chatrooms
# GET /chatrooms.json
def index
#chatrooms = Chatroom.public_channels.page(params[:page]).per(40)
#chatroom_categories = Chatroom.public_channels.page(params[:page]).per(26)
end
# GET /chatrooms/1
# GET /chatrooms/1.json
def show
#messages = #chatroom.messages.order(created_at: :desc).limit(100).reverse
#chatroom_user = current_user.chatroom_users.find_by(chatroom_id: #chatroom.id)
end
# GET /chatrooms/new
def new
#chatroom = Chatroom.new(user_id: current_user.id)
end
# GET /chatrooms/1/edit
def edit
end
# POST /chatrooms
# POST /chatrooms.json
def create
#chatroom = current_user.chatrooms.build(chatroom_params)
respond_to do |format|
if #chatroom.save
#chatroom.chatroom_users.where(user_id: current_user.id).first_or_create
format.html {redirect_to #chatroom, notice: 'Chatroom was successfully created.'}
format.json {render :show, status: :created, location: #chatroom}
else
format.html {render :new}
format.json {render json: #chatroom.errors, status: :unprocessable_entity}
end
end
end
# PATCH/PUT /chatrooms/1
# PATCH/PUT /chatrooms/1.json
def update
respond_to do |format|
if #chatroom.update(chatroom_params)
format.html {redirect_to #chatroom, notice: 'Chatroom was successfully updated.'}
format.json {render :show, status: :ok, location: #chatroom}
else
format.html {render :edit}
format.json {render json: #chatroom.errors, status: :unprocessable_entity}
end
end
end
# DELETE /chatrooms/1
# DELETE /chatrooms/1.json
def destroy
if current_user == #chatroom.user
#chatroom.destroy
respond_to do |format|
format.html {redirect_to chatrooms_url, notice: 'Chatroom was successfully destroyed.'}
format.json {head :no_content}
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_chatroom
#chatroom = Chatroom.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def chatroom_params
params.require(:chatroom).permit(:name, :category_id, :chat_name_color, :user_id)
end
schema.rb
create_table "chatroom_users", force: :cascade do |t|
t.bigint "chatroom_id"
t.bigint "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "last_read_at"
t.index ["chatroom_id"], name: "index_chatroom_users_on_chatroom_id"
t.index ["user_id"], name: "index_chatroom_users_on_user_id"
end
create_table "chatrooms", force: :cascade do |t|
t.bigint "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "direct_message", default: false
t.string "name"
t.string "chat_name_color"
t.integer "category_id"
t.index ["category_id"], name: "index_chatrooms_on_category_id"
t.index ["user_id"], name: "index_chatrooms_on_user_id"
end
chatroom_user.rb
class ChatroomUser < ApplicationRecord
belongs_to :chatroom
belongs_to :user
before_create :set_last_read
def set_last_read
self.last_read_at = Time.zone.now
end
end
In your Destroy action you have if current_user == #chatroom.user, not entirely sure #chatroom.user will bring out the correct info, but to give the creator of a chatroom the ability to delete a chatroom, you might want to add a creator column to chatroom table and save maybe the username, then in your destroy action compare current_user.name == #chatroom.creator.
Or better still remove the condition in the destroy action and make the delete button only be visible if current_user.name == #chatroom.creator
I would like to display my orders like the ingredients are displayed just above. And I don't understand why is not ??
Post : Ingredients nested
Onlines :Orders nested
Views/posts/show:
<p>
<strong>Title:</strong>
<%= #post.title %>
</p>
<p> Posted by : <%= link_to #post.user.pseudo, profile_path(#post.user.pseudo) %>, <%= time_ago_in_words(#post.created_at) %> ago </p>
<p>
<strong>Image:</strong>
<%= image_tag #post.image.url(:medium) %>
</p>
<p>
<strong>Description:</strong>
<%= #post.description %>
</p>
<div class="btn-group" role="group" aria-label="...">
<%= link_to '- Pusher - ', new_post_online_path(#post), data: { confirm: 'Confirmer la mise en ligne de #{#title}?' }, class: "btn btn-primary " %>
<div class="col-md-12">
<h3>Ingrédients :</h3>
<div id="ingredients">
<ul>
<%- #post.ingredients.each do |ingredient| %>
<li>
<%= ingredient.name %>
</li>
<%end%>
</ul>
</div>
</div>
<br>
<div class="col-md-9">
<h3>Parts :</h3>
<div id="ingredients">
<ul>
<%- #post.onlines.orders.each do |order| %>
<li>
<%= order.id %>
</li>
<%end%>
</ul>
</div>
</div>
<%= link_to 'Patcher', edit_post_online_path(#post, #post.onlines.last), class: "btn btn-warning"%>
</div>
post controller:
class PostsController < ApplicationController
before_action :authenticate_user!
before_action :set_post, only: [:show, :edit, :update, :destroy]
before_action :owned_post, only: [:edit, :update, :destroy]
# GET /posts
# GET /posts.json
def index
#posts = Post.push_posts
end
# GET /posts/1
# GET /posts/1.json
def show
end
# GET /posts/new
def new
#post = current_user.posts.build
end
# GET /posts/1/edit
def edit
end
# POST /posts
# POST /posts.json
def create
#post = current_user.posts.build(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: #post }
else
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #post }
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:user_id, :title, :description, :image, ingredients_attributes: [:id, :name, :_destroy])
end
def owned_post
unless current_user == #post.user
flash[:alert] = "That post doesn't belong to you!"
redirect_to root_path
end
end
def set_online
#onlines = Online.find_by(params[:id])
end
end
Onlines controller:
class OnlinesController < ApplicationController
before_action :authenticate_user!
before_action :set_post
before_action :owned_online, only: [:new, :update]
before_action :set_online
def new
#online = current_user.onlines.build
#online.post_id = #post.id
#online.user_id = current_user.id
end
def edit
end
def taked
#online.orders.update(taked: false)
end
def create
if Online.where(post_id: params[:post_id]).any?
#online = Online.where(post_id: params[:post_id]).last.update_attributes(push: false)
end
#online = #post.onlines.create(online_params)
if #online.save
if #online.portion <= 0
#online.update(push: false)
flash[:success] = 'Veuillez indiquer le nombre de parts disponibles '
redirect_to root_path
else
#online.update(pushed_at: Time.zone.now)
#online.update(push: true)
flash[:success] = 'Votre post est en ligne !'
redirect_to root_path
end
else
render 'new'
end
end
def update
if #onlines.update(online_params)
if #online.push == false
if #online.portion <= 0
#online.update(push: false)
flash[:success] = 'Veuillez indiquer le nombre de parts disponibles '
redirect_to root_path
else
#online.update(push: true)
flash[:success] = 'Votre post a bien été pushé !'
redirect_to root_path
end
end
else
#user.errors.full_messages
flash[:error] = #user.errors.full_messages
render :edit
end
end
private
def online_params
params.require(:online).permit(:user_id, :post_id, :prix, :portion, :push, :pushed_at, orders_attributes: [:id, :taked, :taked_at, :taked_by, :validated_at, :validated_by, :_destroy])
end
def owned_online
#post = Post.find(params[:post_id])
unless current_user == #post.user
flash[:alert] = "That post doesn't belong to you!"
redirect_to :back
end
end
def set_post
#post = Post.find_by(params[:post_id])
end
def set_online
#post = Post.find(params[:post_id])
#online = Online.find_by(params[:id])
end
end
models
online :
class Online < ActiveRecord::Base
belongs_to :post
belongs_to :user
has_many :orders
accepts_nested_attributes_for :orders, allow_destroy: true
scope :push, ->{ where(push: true).order("pushed_at DESC") }
end
orders :
class Order < ActiveRecord::Base
belongs_to :online
belongs_to :user
end
and post :
class Post < ActiveRecord::Base
belongs_to :user
has_many :onlines, dependent: :destroy
scope :push_posts, lambda { joins(:onlines).merge(Online.push) }
has_many :ingredients, dependent: :destroy
accepts_nested_attributes_for :ingredients, reject_if: :all_blank, allow_destroy: true
has_many :comments
validates :image, presence: true
has_attached_file :image, styles: { medium: "300x300#"}, default_url: "/images/:style/missing.png"
validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/
end
So if you have the solution above, I'll take it !!
Thanks
Your Posts have many Onlines. Each Online has many Orders. So, you should iterate through each order of each online in your post.
<ul>
<%- #post.onlines.each do |online| %>
<%- online.orders.each do |order| %>
<li>
<%= order.id %>
</li>
<%end%>
<%end%>
</ul>
I came across a problem in my web app.
I would like to make a mvc to allow the user create a push from the post (like a ranking or commments). But actualy, the push is creating automatically when the user show the post. So I want this one is created if the user submit the data pushed.
Can you explain me where I make a mistake ?
My code
Show/post view :
<strong>Title:</strong>
<%= #post.title %>
</p>
<p>
<strong>Image:</strong>
<%= image_tag #post.image.url(:medium) %>
</p>
<p>
<strong>Prix:</strong>
<%= #post.prix %>
</p>
<p>
<strong>Description:</strong>
<%= #post.description %>
</p>
<%- if current_user.admin? %>
<div class="btn-group" role="group" aria-label="...">
<%= link_to 'Modifier', edit_post_path(#post), class: "btn btn-warning"%>
<%= link_to 'Supprimer', #post, method: :delete, data: { confirm: 'Confirmer la suppression du plat ?' }, class: "btn btn-danger" %>
<%end%>
<%=link_to "Home", posts_path, class: "btn btn-info"%>
</div>
<div class= "col-md-6">
<div class="push">
<%= render 'pushs/form' %>
</div>
</div>
Push/form (into the views/posts/show) :
<%= simple_form_for([#post, #post.pushs.build]) do |f| %>
<div class="row">
<div class="col-md-12">
<div class="form-group text-center">
<h4>Combien êtes vous ?</h4>
<%= f.text_field :quantity %>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group text-center">
<h4>Ou êtes vous ?</h4>
<%= f.text_field :adress2 %>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group text-center">
<%= f.button :submit %>
</div>
</div>
</div>
<% end %>
the Push controller :
class PushsController < ApplicationController
before_action :authenticate_user!
before_action :set_post
before_action :set_push, only: [:edit, :update, :destroy]
def create
#push = #post.pushs.create(push_params)
#push.user_id = current_user.id
if #push.save
flash[:success] = 'Votre commande est enregisté !'
redirect_to root_path
else
flash[:alert] = "Check the push form, something went horribly wrong."
redirect_to root_path
end
end
def update
if #push.update(push_params)
flash[:success] = 'Votre commande est enregisté !'
redirect_to root_path
else
flash[:alert] = "Check the push form, something went horribly wrong."
render 'edit'
end
end
def destroy
#push = #post.pushs.find(params[:id])
#push.destroy
flash[:success] = "Push deleted :("
redirect_to root_path
end
private
def push_params
params.require(:push).permit(:user_id, :quantity, :prix2, :time, :adress2, :latitude2, :longitude2, :taked, :taked_by, :taked_at, :validated)
end
def set_post
#post = Post.find(params[:post_id])
end
def set_push
#post = Post.find(params[:post_id])
#push = #post.pushs.find(params[:id])
end
end
& the post controller :
class PostsController < ApplicationController
before_action :authenticate_user!
before_action :set_post, only: [:show, :edit, :update, :destroy]
before_action :post_admin, only: [:new, :edit, :update, :destroy]
# GET /posts
# GET /posts.json
def index
#posts = Post.all
end
# GET /posts/1
# GET /posts/1.json
def show
end
# GET /posts/new
def new
#post = Post.new
end
# GET /posts/1/edit
def edit
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: #post }
else
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #post }
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = Post.find(params[:id])
end
def post_admin
if current_user.admin?
else
flash[:alert] = "That post doesn't belong to you!"
redirect_to root_path
end
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:user_id, :title, :prix, :image, :description, :user_id)
end
end
Thanks, and obviously if you have any suggestions, I am eager to learn
Bye
I'm trying to create a new location and a devise user in the same form and link them. The user and the location are created, but the location_id is not saving to the user. There is a location_id column in the user table.
My form
<% resource.build_location %>
<%= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => {:class => 'form-vertical' }) do |f| %>
<%= f.error_notification %>
<!-- capture location details hidden values -->
<%= f.fields_for :location do |location_form| %>
<%= location_form.text_field :name, :name => "name", :type => "hidden" %>
<%= location_form.text_field :street_address, :name => "formatted_address", :type => "hidden" %>
<%= location_form.text_field :lat, :name => "lat", :type => "hidden" %>
<%= location_form.text_field :long, :name => "lng", :type => "hidden" %>
<% end %>
<!-- devise user authenticate -->
<%= f.input :name, :autofocus => true %>
<%= f.input :email, :required => true %>
<%= f.input :password, :required => true %>
<%= f.input :password_confirmation, :required => true %>
<%= f.button :submit, 'Sign up', :class => 'btn-primary' %>
<% end %>
<%= render "devise/shared/links" %>
Location model
class Location < ActiveRecord::Base
has_many :users, :dependent => :destroy
accepts_nested_attributes_for :users, :allow_destroy => true
attr_accessible :lat, :long, :name, :street_address
attr_accessible :user_attributes
end
Location controller
def new
#location = Location.new
#location.user.build
respond_to do |format|
format.html # new.html.erb
format.json { render json: #location }
end
end
# GET /locations/1/edit
def edit
#location = Location.find(params[:id])
end
# POST /locations
# POST /locations.json
def create
#location = #user.location.build(params[:location])
respond_to do |format|
if #location.save
format.html { redirect_to #location, notice: 'Location was successfully created.' }
format.json { render json: #location, status: :created, location: #location }
else
format.html { render action: "new" }
format.json { render json: #location.errors, status: :unprocessable_entity }
end
end
end
User Model
class User < ActiveRecord::Base
belongs_to :location
accepts_nested_attributes_for :location
rolify
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :role_ids, :as => :admin
attr_accessible :name, :email, :password, :password_confirmation, :remember_me, :location, :location_id, :location_attributes
end
User controller
class UsersController < ApplicationController
before_filter :authenticate_user!
def index
authorize! :index, #user, :message => 'Not authorized as an administrator.'
#users = User.all
end
def show
#user = User.find(params[:id])
end
def update
authorize! :update, #user, :message => 'Not authorized as an administrator.'
#user = User.find(params[:id])
if #user.update_attributes(params[:user], :as => :admin)
redirect_to users_path, :notice => "User updated."
else
redirect_to users_path, :alert => "Unable to update user."
end
end
def destroy
authorize! :destroy, #user, :message => 'Not authorized as an administrator.'
user = User.find(params[:id])
unless user == current_user
user.destroy
redirect_to users_path, :notice => "User deleted."
else
redirect_to users_path, :notice => "Can't delete yourself."
end
end
end
No errors when creating the user, just getting a location_id="nil" when creating the user. I can access the location and a location_id is created but not linked to the user. Any ideas on how to save the location_id to the user?
I am populating the location info with json returned from a google location api autocomplete and assigning to an element with name="". It seems that everything works fine when I manually enter location info, but fails when the fields are populated from the autocomplete.
The first thing to note is that you do not need accepts_nested_attributes_for on both models, only the one that has the has_many association. Also, it looks like the pluralization is wrong in the Location model for users attributes
class Location < ActiveRecord::Base
has_many :users, :dependent => :destroy
accepts_nested_attributes_for :users, :allow_destroy => true
attr_accessible :lat, :long, :name, :street_address
attr_accessible :users_attributes # <- This should be plural
end
Remove the accepts_nested_attributes_for in the user model
class User < ActiveRecord::Base
belongs_to :location
accepts_nested_attributes_for :location # <- This should be removed
rolify
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :role_ids, :as => :admin
attr_accessible :name, :email, :password, :password_confirmation, :remember_me, :location, :location_id # Also remove location_atributes
end
Also, this line
#location = #user.location.build(params[:location])
Should be
#location = Location.new(params[:location)
since the way your models are setup now a location has a user so you do not need to build a location from a user. That being said, I would recommend you create the association in the opposite direction where a user has_many locations, but this of course may be contrary to your function so take it with a grain of salt :).
http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html