Bazley
Bazley

Reputation: 2847

Rails strong params TypeError no implicit conversion of Symbol into Integer

Why am I getting this error?:

TypeError (no implicit conversion of Symbol into Integer)

in the create action in the posts_controller:

posts_controller.rb

@post = @character.posts.create(post_params)
...

def post_params
  params.require(:post).permit( conversation_attributes: [ missives_attributes: [ :content ] ] )
end

post.rb

has_one :conversation, class_name: 'Postconversation', dependent: :destroy
accepts_nested_attributes_for :conversation

postconversation.rb

has_many :missives, class_name: 'Postmissive', dependent: :destroy
accepts_nested_attributes_for :missives

_post_form.html.erb

<%= f.fields_for :conversation_attributes do |ff| %>
  <%= ff.fields_for :missives_attributes do |fff| %>
    <%= hidden_field_tag :callsign, character.callsign %>
    <%= fff.text_area :content %>
    ...
  <% end %>
<% end %>

Logs

Parameters: {"utf8"=>"✓", "authenticity_token"=>"mxHD...VoA==", "callsign"=>"baz", "post"=>{"conversation_attributes"=>{"missives_attributes"=>{"content"=>"Hello"}}}}

EDIT

According to this question, it looks like I need square brackets around my submitted parameters: Strong parameters with has_many gives "no implicit conversion of Symbol into Integer"

Parameters: {"utf8"=>"✓", "authenticity_token"=>"mxHD...VoA==", "callsign"=>"baz", "post"=>{"conversation_attributes"=> [ {"missives_attributes"=> [ {"content"=>"Hello"} ] } ] }}

But how do I achieve this in the post form??

Upvotes: 0

Views: 874

Answers (2)

Bazley
Bazley

Reputation: 2847

I finally got it working:

posts_controller.rb

@post = @character.posts.create(post_params)
...

def post_params
  params.require(:post).permit( conversation_attributes: [ missives_attributes: [ :content ] ] )
end

post.rb

has_one :conversation, class_name: 'Postconversation', dependent: :destroy, inverse_of: :post
accepts_nested_attributes_for :conversation

postconversation.rb

belongs_to :post, inverse_of: :conversation
has_many :missives, class_name: 'Postmissive', dependent: :destroy, foreign_key: 'conversation_id', inverse_of: :conversation
accepts_nested_attributes_for :missives

postmissive.rb

belongs_to :conversation, class_name: 'Postconversation', foreign_key: 'conversation_id', inverse_of: :missives
validates :conversation, presence: true # validates :conversation_id does not work

_post_form.html.erb

<%= f.fields_for :conversation_attributes do |ff| %>
  <%= ff.fields_for 'missives_attributes[]', Postmissive.new do |fff| %>
    <%= hidden_field_tag :callsign, character.callsign %>
    <%= fff.text_area :content %>
    ...
  <% end %>
<% end %>

Submitted Parameters

Parameters: {"utf8"=>"✓", "authenticity_token"=>"mxHD...VoA==", "callsign"=>"baz", "post"=>{"conversation_attributes"=>{"missives_attributes"=>[{"content"=>"Hello"}]}}}

Notes

1) Note the addition of inverse_of: so Rails recognises the bi-directional association. The database save fails without this. The docs say it's only necessary to use with has_one and has_many, but some Stack Overflow answers say it should also be used with the belongs_to, so that's what I've done (belongs_to :post, inverse_of: :conversation and belongs_to :conversation, inverse_of: :missives). Further insight on this welcome.

2) post_params are fine as is. No need for the addition of any brackets.

3) In postmissive.rb, the validation had to be validates :conversation, not validates :conversation_id.

4) Stephan Wiehr was right, the missives_attributes had to be submitted as an array. Thanks to Kartikey Tanna for this answer on how to achieve this.

Upvotes: 1

Sravan
Sravan

Reputation: 18647

Since, missives_attributes contain content

You shld use, <%= fff.text_area :content %> for missives_attributes and not <%= f.text_area :content %>

<%= f.fields_for :conversation_attributes do |ff| %>
  <%= ff.fields_for :missives_attributes do |fff| %>
    <%= hidden_field_tag :callsign, character.callsign %>
    <%= fff.text_area :content %>
    ...
  <% end %>
<% end %>

Upvotes: 1

Related Questions