强参数:不允许的参数:has_many_through 关系中的标签
Strong parameters: Unpermitted parameters: tags in has_many_through relation
我有几个models/controllers:
event.rb:
class Event < ActiveRecord::Base
belongs_to :category
belongs_to :user
has_many :event_tags
has_many :tags, through: :event_tags
has_many :event_skills
has_many :skills, through: :event_skills
tag.rb
class Tag < ActiveRecord::Base
has_many :events, through: :event_tags
has_many :event_tags
end
event_tag.rb
class EventTag < ActiveRecord::Base
belongs_to :event
belongs_to :tag
end
user.rb:
class User < ActiveRecord::Base
has_many :events # organized_events
events_controller.rb
class EventsController < ApplicationController
...
def create
@event = Event.new(event_params)
@event.user_id = current_user.id
respond_to do |format|
if @event.save
format.html { redirect_to @event, notice: 'L\'évènement a été crée.' }
format.json { render json: @event, status: :created, location: @event }
else
format.html { render action: "new" }
format.json { render json: @event.errors, status: :unprocessable_entity }
end
end
end
...
private
def event_params
params[:event][:date] = '%s %s' % [params[:event][:date].andand.split('/').reverse.join('-'),
params[:event][:hour].andand.sub('h', ':')]
params[:event].delete :hour
params[:event][:tags] = params[:event][:tags].split(';').map { |t| Tag.where(name: t).first_or_create }
params[:event][:skills] = params[:event][:skills].split(';').map { |s| Skill.where(name: s).first_or_create }
binding.pry
params.require(:event).permit(:user_id,
:name,
:date,
:hour,
:description,
:picture,
:category_id,
{tags: []},
{skills: []},
:spots)
我的问题是,当我提交创建活动的表单时,我得到:
Unpermitted parameters: tags
是的,我看过这个 post:Rails 4 Unpermitted Parameters for Array。我试过添加:tags: []
。但这对我来说似乎不起作用。
调试信息:(在上面的 binding.pry 断点处)
[4] pry(#<EventsController>)> params
=> {"utf8"=>"✓",
"authenticity_token"=>"634lFWEsVDCD+yqPKBigmEJB0kRdHlLmyJpRwjTTVhU=",
"event"=>
{"name"=>"test tag 17",
"category_id"=>"1",
"date"=>" ",
"tags"=>
[#<Tag id: 3, name: "beer", created_at: "2014-12-05 11:21:27", updated_at: "2014-12-05 11:21:27">,
#<Tag id: 4, name: "vodka", created_at: "2014-12-05 11:21:27", updated_at: "2014-12-05 11:21:27">,
#<Tag id: 5, name: "champain", created_at: "2014-12-05 11:21:27", updated_at: "2014-12-05 11:21:27">],
"skills"=>[],
"spots"=>"",
"description"=>"sdfsf"},
"action"=>"create",
"controller"=>"events"}
[5] pry(#<EventsController>)> event_params
Unpermitted parameters: tags
=> {"name"=>"test tag 17", "date"=>" ", "description"=>"sdfsf", "category_id"=>"1", "skills"=>[], "spots"=>""}
[6] pry(#<EventsController>)>
- 如何正确地允许
:tags
参数?
- 我是否应该以不同方式处理标签的提交(例如:event_params 方法是否适合使用拆分进行解析)?
来自docs
Only permitted scalars pass the filter. ... passes params whose associated value is of type String, Symbol, NilClass, Numeric, TrueClass, FalseClass, Date, Time, DateTime, StringIO, IO, ActionDispatch::Http::UploadedFile or Rack::Test::UploadedFile. Otherwise, the key :name is filtered out.
在允许属性之前,您不能将标签数组元素转换为 AR 对象。你首先需要允许参数,然后你可以用对象改变它。
更新:
查看 railscasts 你可以看到一个模型,有一个方法:tagged_with
您可以创建:
class Event < ActiveRecord::Base
def tagged_with(*tag_names)
# create (or build) your tags
end
end
在你的控制器中,你会有 event_params
、tag_params
和 skill_params
def create
@event = Event.new(event_params)
@event.tagged_with(tag_params)
# Same thing with skills
@event.user_id = current_user.id
...
end
...
def tag_params
params.require(:event).permit(tags: [])
end
感谢@Magnuss 指出问题。 (我不能允许 AR 类型的对象)。
我最终将我的控制器更改为:(现在它工作正常)
class EventsController < ApplicationController
...
def create
# added parse_event_params here. Also added in update method, not shown here.
@event = Event.new(parse_event_params event_params)
@event.user_id = current_user.id
respond_to do |format|
if @event.save
format.html { redirect_to @event, notice: 'L\'évènement a été crée.' }
format.json { render json: @event, status: :created, location: @event }
else
format.html { render action: "new" }
format.json { render json: @event.errors, status: :unprocessable_entity }
end
end
end
private
# added this method
def parse_event_params(event_params)
event_params[:date] = '%s %s' % [event_params[:date].andand.split('/').reverse.join('-'),
event_params[:hour].andand.sub('h', ':')]
event_params.delete :hour
event_params[:tags] = event_params[:tags].split(';').map { |t| Tag.where(name: t).first_or_create }
event_params[:skills] = event_params[:skills].split(';').map { |s| Skill.where(name: s).first_or_create }
event_params
end
# changed this method so it's only doing require/permit
def event_params
params.require(:event).permit(:user_id,
:name,
:date,
:hour,
:description,
:picture,
:category_id,
:tags,
:skills,
:spots)
end
我有几个models/controllers:
event.rb:
class Event < ActiveRecord::Base
belongs_to :category
belongs_to :user
has_many :event_tags
has_many :tags, through: :event_tags
has_many :event_skills
has_many :skills, through: :event_skills
tag.rb
class Tag < ActiveRecord::Base
has_many :events, through: :event_tags
has_many :event_tags
end
event_tag.rb
class EventTag < ActiveRecord::Base
belongs_to :event
belongs_to :tag
end
user.rb:
class User < ActiveRecord::Base
has_many :events # organized_events
events_controller.rb
class EventsController < ApplicationController
...
def create
@event = Event.new(event_params)
@event.user_id = current_user.id
respond_to do |format|
if @event.save
format.html { redirect_to @event, notice: 'L\'évènement a été crée.' }
format.json { render json: @event, status: :created, location: @event }
else
format.html { render action: "new" }
format.json { render json: @event.errors, status: :unprocessable_entity }
end
end
end
...
private
def event_params
params[:event][:date] = '%s %s' % [params[:event][:date].andand.split('/').reverse.join('-'),
params[:event][:hour].andand.sub('h', ':')]
params[:event].delete :hour
params[:event][:tags] = params[:event][:tags].split(';').map { |t| Tag.where(name: t).first_or_create }
params[:event][:skills] = params[:event][:skills].split(';').map { |s| Skill.where(name: s).first_or_create }
binding.pry
params.require(:event).permit(:user_id,
:name,
:date,
:hour,
:description,
:picture,
:category_id,
{tags: []},
{skills: []},
:spots)
我的问题是,当我提交创建活动的表单时,我得到:
Unpermitted parameters: tags
是的,我看过这个 post:Rails 4 Unpermitted Parameters for Array。我试过添加:tags: []
。但这对我来说似乎不起作用。
调试信息:(在上面的 binding.pry 断点处)
[4] pry(#<EventsController>)> params
=> {"utf8"=>"✓",
"authenticity_token"=>"634lFWEsVDCD+yqPKBigmEJB0kRdHlLmyJpRwjTTVhU=",
"event"=>
{"name"=>"test tag 17",
"category_id"=>"1",
"date"=>" ",
"tags"=>
[#<Tag id: 3, name: "beer", created_at: "2014-12-05 11:21:27", updated_at: "2014-12-05 11:21:27">,
#<Tag id: 4, name: "vodka", created_at: "2014-12-05 11:21:27", updated_at: "2014-12-05 11:21:27">,
#<Tag id: 5, name: "champain", created_at: "2014-12-05 11:21:27", updated_at: "2014-12-05 11:21:27">],
"skills"=>[],
"spots"=>"",
"description"=>"sdfsf"},
"action"=>"create",
"controller"=>"events"}
[5] pry(#<EventsController>)> event_params
Unpermitted parameters: tags
=> {"name"=>"test tag 17", "date"=>" ", "description"=>"sdfsf", "category_id"=>"1", "skills"=>[], "spots"=>""}
[6] pry(#<EventsController>)>
- 如何正确地允许
:tags
参数? - 我是否应该以不同方式处理标签的提交(例如:event_params 方法是否适合使用拆分进行解析)?
来自docs
Only permitted scalars pass the filter. ... passes params whose associated value is of type String, Symbol, NilClass, Numeric, TrueClass, FalseClass, Date, Time, DateTime, StringIO, IO, ActionDispatch::Http::UploadedFile or Rack::Test::UploadedFile. Otherwise, the key :name is filtered out.
在允许属性之前,您不能将标签数组元素转换为 AR 对象。你首先需要允许参数,然后你可以用对象改变它。
更新:
查看 railscasts 你可以看到一个模型,有一个方法:tagged_with
您可以创建:
class Event < ActiveRecord::Base
def tagged_with(*tag_names)
# create (or build) your tags
end
end
在你的控制器中,你会有 event_params
、tag_params
和 skill_params
def create
@event = Event.new(event_params)
@event.tagged_with(tag_params)
# Same thing with skills
@event.user_id = current_user.id
...
end
...
def tag_params
params.require(:event).permit(tags: [])
end
感谢@Magnuss 指出问题。 (我不能允许 AR 类型的对象)。
我最终将我的控制器更改为:(现在它工作正常)
class EventsController < ApplicationController
...
def create
# added parse_event_params here. Also added in update method, not shown here.
@event = Event.new(parse_event_params event_params)
@event.user_id = current_user.id
respond_to do |format|
if @event.save
format.html { redirect_to @event, notice: 'L\'évènement a été crée.' }
format.json { render json: @event, status: :created, location: @event }
else
format.html { render action: "new" }
format.json { render json: @event.errors, status: :unprocessable_entity }
end
end
end
private
# added this method
def parse_event_params(event_params)
event_params[:date] = '%s %s' % [event_params[:date].andand.split('/').reverse.join('-'),
event_params[:hour].andand.sub('h', ':')]
event_params.delete :hour
event_params[:tags] = event_params[:tags].split(';').map { |t| Tag.where(name: t).first_or_create }
event_params[:skills] = event_params[:skills].split(';').map { |s| Skill.where(name: s).first_or_create }
event_params
end
# changed this method so it's only doing require/permit
def event_params
params.require(:event).permit(:user_id,
:name,
:date,
:hour,
:description,
:picture,
:category_id,
:tags,
:skills,
:spots)
end