I have a few 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)
My problem is that when I submit the form to create an event, I get:
Unpermitted parameters: tags
Yes, I've seen this post: Rails 4 Unpermitted Parameters for Array. And I've tried adding: tags: []
. But it doesn't seem to work in my case.
Debug info: (at the binding.pry breakpoint you see above)
[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>)>
- How do I properly permit the
:tags
param ? - Should I handle the submission of the tags differently (eg: is the event_params method the right place to do the parsing with split) ?
From 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.
You cannot convert tag array elements to AR objects before you permit the attributes. You first need to permit the params, then you can mutate it with objects.
Updated:
Looking at railscasts you can see that a model, has a method: tagged_with
You could create:
class Event < ActiveRecord::Base
def tagged_with(*tag_names)
# create (or build) your tags
end
end
In your controller, you'd have event_params
, tag_params
and 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
Thanks @Magnuss for pointing out the problem. (I cannot permit an object of AR type).
I ended up changing my controller to this: (And now it works fine)
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
来源:https://stackoverflow.com/questions/28049879/strong-parameters-unpermitted-parameters-tags-in-has-many-through-relation