轨嵌套的资源:控制器,并形成
我建立一个轨道的网站,是有gyms
和reviews
。我希望用户能够为健身房留下评论。我有我的表设置为轨嵌套的资源:控制器,并形成
class Gym < ActiveRecord::Base
has_many :pictures, as: :imageable
has_many :reviews
end
和
class Review < ActiveRecord::Base
belongs_to :user
belongs_to :gym
validates :body, presence: true, length: { maximum: 1000 }
validates :rating, presence: true
end
眼下健身房控制器是静态的(不能CRUD健身房,因为这是一个管理的事情),只是呈现的页面W /信息。我正在尝试添加评论,但我不想混淆关联。这里是我的健身房控制器信息
class GymsController < ApplicationController
before_action :logged_in_user, only: [:index, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update]
def index
@q = Gym.ransack(params[:q])
@gyms = @q.result
@other_gyms = Gym.all
if @gyms.to_a.count < 1
flash[:warning] = "No gym matched #{params[:q][:name_or_phone_number_or_city_or_zip_code_cont]}"
end
end
def new
@gym = Gym.find(params[:id])
@review = @gym.review.new
end
def create
@gym = Gym.find(params[:id])
@review = @gym.reviews.build(gym_params)
if @review.save
flash[:success] = 'Review Saved'
redirect_to :back
else
render 'new'
end
end
def show
@gym = Gym.find(params[:id])
@reviews = @gym.reviews
end
private
def gym_params
params.require(:gym).permit(:name, :description, :address, :address_2, :zip_code,
:phone_number, :website_url, :city, :state, :latitude, :longitude,
review_attributes: [:user_id, :rating, :body, :gym_id])
end
def logged_in_user
unless logged_in?
store_location
flash[:danger] = 'Please log in'
redirect_to login_url
end
end
def correct_user
@user = User.find(params[:id])
redirect_to(root_url) unless current_user?(@user)
end
end
我的路线
resources :gyms, only: [:index, :show] do
resources :reviews
end
和健身房/显示link_to
指向gyms/:id/reviews
在健身房/新我有评论表
<%= form_for [@gym, @review] do |f| %>
<%= f.label :rating, 'Select your rating' %>
<div id='ratyRating'></div><br>
<%= f.text_area :body, size: '100x10' %>
<%= f.hidden_field :user_id, value: current_user.id %>
<%= f.submit 'Post', class: 'btn btn-gen' %>
<% end %>
第
是行不通的。并从link_to按钮,我得到它指向gyms/:id/reviews
这是一个索引页。我觉得有更好的方法来做到这一点。有没有人看到我在这里做错了?
从控制台运行$ rake routes
开始。这会告诉你,POST /gyms/:gym_id/reviews
将ReviewsController
不GymsController
处理。
这也正是理所应当的,因为每个控制器应该只负责CRUD'ing一个单一的资源。
class ReviewsController < ApplicationController
before_action :set_gym!
# GET /gyms/:gym_id/reviews
def index
@reviews = @gym.reviews
end
# POST /gyms/:gym_id/reviews
def create
@review = @gym.reviews.new(review_params) do |r|
r.user = current_user
end
if @review.save
redirect_to @gym, success: 'Review created!'
else
render :new
end
end
private
def set_gym!
@gym = Gym.find(params[:gym_id])
end
def review_params
params.require(:review).permit(:body)
end
end
有些事情要注意这里 - 不要通过表单传递用户ID。它使得它很容易被欺骗。而是从会话或令牌获取当前用户。
让我们创建一个局部的形式:
<%= form_for [gym, review] do |f| %>
<%= f.label :rating, 'Select your rating' %>
<%= f.text_area :body, size: '100x10' %>
<%= f.submit 'Post', class: 'btn btn-gen' %>
<% end %>
然后当需要reviews/new.html.erb
视图如果审查无效时呈现:
<%= render partial: 'form', gym: @gym, review: @review %>
然后我们还可以嵌入gyms/show.html.erb
形式:
<%= render partial: 'reviews/form', gym: @gym, review: @gym.reviews.new %>
它看起来像你正试图创建一个从健身房控制器review
。这将是一个嵌套形式,这需要在你的健身房模型accepts_nested_attributes_for
:
class Gym < ActiveRecord::Base
has_many :pictures, as: :imageable
has_many :reviews
accepts_nested_attributes_for :reviews
end
你的形式需要与fields_for
返工:
<%= form_for @gym do |f| %>
<%= f.fields_for :reviews do |reviews_form| %>
<%= reviews_form.label :rating, 'Select your rating' %>
<div id='ratyRating'></div><br>
<%= reviews_form.text_area :body, size: '100x10' %>
<%= reviews_form.hidden_field :user_id, value: current_user.id %>
<% end %>
<%= f.submit 'Post', class: 'btn btn-gen' %>
<% end %>
你gym_params需要看起来像这样与reviews_attributes
,不review_attributes
def gym_params
params.require(:gym).permit(:name, :description, :address, :address_2, :zip_code,
:phone_number, :website_url, :city, :state, :latitude, :longitude,
reviews_attributes: [:user_id, :rating, :body, :gym_id])
end
在
new
行动
然后,你正在创建一个新的Gym
实例,你缺少的review
复数当你创建一个@review
比如在:
@gym = Gym.new
@review = @gym.reviews.build
记住,gym
has_many
reviews
- 所以你要在可能时使用复数reviews
。
不知道如果我抓住了一切,但我会建议检查出的Rails上Nested Forms指导,部分9.2一个很好的解释。嵌套表单可能会很棘手,另一个更简单的选项是在评论控制器中创建一个单独的评论表单(请参阅@ max的答案)
我看到一堆东西出错了,在这里你的'correct_user'过滤器获取用户来自'params [:id]'的id。 ''flash [:warning] =“没有健身房匹配#{params [:q] [:name_or_phone_number_or_city_or_zip_code_cont]}”'暴露您的用户注入漏洞,因为您正在回显参数。 – max
感谢您的支持!我不知道。你能详细解释一下吗? –
http://guides.rubyonrails.org/security.html#cross-site-scripting-xss – max