I am trying to use formtastic to make a form where I can enter an :opposition choose a :venue and a :team and then be presented with a list of players that I am able to check off to select them for the
I have got the form set up so it renders correctly however when submitted it does not save any information and just reloads the page.
My code is at my github here: https://github.com/jpknegtel/st_francis
models
This concerns the following models:
player
has_many :player_fixtures
has_many :fixtures, :through => :player_fixtures
fixtures
has_many :player_fixtures
has_many :players, :through => :player_fixtures
PlayerFixture
belongs_to :player
belongs_to :fixture
controller
def create
#fixture = Fixture.new(params[:fixture])
if #fixture.save
flash[:notice] = "Fixture Created"
redirect_to(:action =>'list')
else
flash.now[:error] = "Could not save fixture. Please re-enter information"
render('new')
end
end
def new
#fixture = Fixture.new
end
form
<%= semantic_form_for :fixture do |f| %>
<%= f.inputs do %>
<%= f.input :opposition %>
<%= f.input :team, :as => :select, :collection => Team.all %>
<%= f.input :venue, :as => :check_boxes, :collection => Hash[Venue.all.map{|b| [b.name, b.id]}]%>
<%= f.input :players, :as => :check_boxes, :collection => Hash[Player.all.map{|b| [b.full_name, b.id]}], :required => true %>
<% end %>
<%= f.actions do %>
<%= f.action :submit, :as => :button %>
<%= f.action :cancel, :as => :link %>
<% end %>
<% end %>
So when the form is submitted now nothing is passed. When looking at the web brick server nothing gets submitted but the page just gets reloaded.
It is possible to insert the records using rails console.
EDIT: I can now see this when submitted.
Started POST "/fixtures/new" for 127.0.0.1 at 2012-04-23 15:00:21 +0100
Processing by FixturesController#new as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Hx4TChWiUdhpZbAfgWUYMWBKao86pZh0tGzwVKy+P80=", "fixture"=> {"opposition"=>"Mid sussex", "team"=>"1", "venue"=>["", "1"], "players"=>["", "1", "3"]}, "button"=>""}
Team Load (1.0ms) SELECT `teams`.* FROM `teams`
Venue Load (1.0ms) SELECT `venues`.* FROM `venues`
Player Load (1.0ms) SELECT `players`.* FROM `players`
Rendered fixtures/new.html.erb within layouts/application (173.0ms)
Completed 200 OK in 200ms (Views: 163.0ms | ActiveRecord: 36.0ms)
[2012-04-23 15:00:21] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true
My guess is massassignment. You need to allow rails to update some attributes via massassignment.
Add this line to your fixtures model:
attr_accessible :players_attributes, :opposition, :team_id, :venue_id, :date
This allows rails to set these attributes via new and update_attributes methods.
See the rails guide on security for more information.
Related
I'm trying to use acts as message able gem and I'm following their example controller
SOLVED See Answer
I keep getting this error undefined method `send_message' for nil:NilClass when trying to send a message in the view
How should I adjust my code?
Thanks
View (Form)
<%= simple_form_for ActsAsMessageable::Message.new, :url => messages_path, :method => :post do |f| %>
<%= f.hidden_field :to, value: #gear.user.email %>
<%= f.input :body %>
<%= f.input :topic %>
<%= f.button :submit, class: 'btn' %>
<% end %>
User Model
class User < ActiveRecord::Base
acts_as_messageable :table_name => "messages", # default 'messages'
:required => [:topic, :body], # default [:topic, :body]
:class_name => "ActsAsMessageable::Message", # default "ActsAsMessageable::Message",
:dependent => :nullify # default :nullify
end
Messages Controller
class MessagesController < ApplicationController
def new
#message = ActsAsMessageable::Message.new
end
def create
#to = User.find_by_email(params[:acts_as_messageable_message][:to])
current_user.send_message(#to, params[:acts_as_messageable_message][:topic], params[:acts_as_messageable_message][:body])
end
end
Development Log
Started POST "/messages" for 127.0.0.1 at 2012-11-15 07:23:40 -0600
Processing by MessagesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"OqaDOP6PldbFVXWPZyijn+887Ym/fDsU0oqzVrL0rQA=", "acts_as_messageable_message"=>{"to"=>"xyz#test.com", "body"=>"test", "topic"=>"test"}, "commit"=>"Create Message"}
[1m[35mUser Load (0.5ms)[0m SELECT `users`.* FROM `users` WHERE `users`.`email` = 'xyz#test.com' LIMIT 1
Completed 500 Internal Server Error in 3ms
NoMethodError (undefined method `send_message' for nil:NilClass):
app/controllers/messages_controller.rb:29:in `create
'
From the error message and provided code seems like your params obj is not formated like you think. Give params[:acts_as_messageable_message] a try instead of [:message]. If that doesn't work check the log to see what is being passed in as params.
I ended up getting it working. The problem ultimately was the gem was using the User model and was expecting the controller to be the User controller not another controller called "Messages". So I simply moved my actions into my Users controller, added the routes and changed the view path, and it now works. #Alex.Bullard thanks for the help.
I'm posting my edits below:
Controller Change
class UsersController < ApplicationController
respond_to :html, :json
def new_message
#message = ActsAsMessageable::Message.new
end
def create_message
#to = User.find_by_email(params[:acts_as_messageable_message][:to])
current_user.send_message(#to, params[:acts_as_messageable_message][:topic], params[:acts_as_messageable_message][:body])
redirect_to :back, notice: "Message sent to Owner"
end
end
View
<%= simple_form_for ActsAsMessageable::Message.new, :url => create_message_users_path, :method => :post do |f| %>
<%= f.hidden_field :to, value: #gear.user.email %>
<%= f.input :body %>
<%= f.input :topic %>
<%= f.button :submit, class: 'btn' %>
<% end %>
Routes
resources :users, :except => [ :create, :new ] do
get "new_message", :on => :collection
post "create_message", :on => :collection
resources :store
end
I have a system setup where users can post microposts (basically status updates) and upload a photo to go with the micropost.
I have:
Micropost model (has_one photo)
Photo_album model (has_many photos)
Photo model (belongs_to micropost, belongs_to photo_album)
User fills in text in text area and selects a photo. Upon submission the microposts table is updated with micropost related data such as content, created_at etc.
At the same time I want my photos table (Photo model) updated with the photo selection the user made but the correct photo album. If you look below you can see in my users_controller the instance variable #photo's value. This insures that the photo uploaded is linked to the correct photo album which is named "microposts album". It's purpose is to link up to all micropost related photos.
I have a Users_controller:
def new
#user = User.new
#micropost = Micropost.new(:user_id => users_id)
#photo = Photo.new(:photo_album_id => PhotoAlbum.where(:user_id => current_user.id, :album_title => "microposts album").first.id)
end
From a previous question I asked it was established I needed to use accepts_nested_attributes_for, fields_for in order to be able to update more than one model with one form. This is how I've set things up.
Micropost model:
class Micropost < ActiveRecord::Base
belongs_to :user
has_one :photo
accepts_nested_attributes_for :photo
attr_accessible :content, :user_id, :poster_id, :username, :image, :remote_image_url
end
Photo model:
class Photo < ActiveRecord::Base
belongs_to :photo_album
attr_accessible :photo_album_id, :photo_title, :image, :remote_image_url
mount_uploader :image, ImageUploader
end
Finally here is the micropost form:
= form_for #micropost, :remote => true do |f|
= f.fields_for #photo do |p|
= p.file_field :image
= f.hidden_field :user_id
= f.text_area :content
= f.submit "Post"
At first I got the error:
ActiveModel::MassAssignmentSecurity::Error (Can't mass-assign protected attributes: photo):
I was slightly confused because I thought the attributes were assigned automatically. At lesast thats what I read in the docs anyway. Anyway I went ahead and added :photo to the micropost model attr_accessible white list.
That first error went then I got this one:
ActiveRecord::AssociationTypeMismatch (Photo(#2169424320) expected, got ActiveSupport::HashWithIndifferentAccess(#2157396720)):
Maybe I've misunderstood how this feature works but I've read through this and also looked at the 3.2.3 api doc but not where I'm going wrong.
I would really appreciate some help with getting this to work.
Thanks in advance and I hope the long post was off putting. Just thought providing all this info would make people understand what I'm trying to do better.
Kind regards
Update:
Using :photo_attributes instead of photos gives me the following error:
Started POST "/microposts" for 127.0.0.1 at 2012-05-10 21:01:11 +0100
[02b23327ad83000f75c418d8739e7f49] [127.0.0.1] Processing by MicropostsController#create as JS
[02b23327ad83000f75c418d8739e7f49] [127.0.0.1] Parameters: {"micropost"=>{"photo"=>{"image"=>#<ActionDispatch::Http::UploadedFile:0x00000102c293d8 #original_filename="7seriesbmw.jpeg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"micropost[photo][image]\"; filename=\"7seriesbmw.jpeg\"\r\nContent-Type: image/jpeg\r\n", #tempfile=#<File:/var/folders/fh/fhADKPjGG8qSuCeoHCTNYE+++TI/-Tmp-/RackMultipart20120510-14787-1e1mrhh>>}, "user_id"=>"2", "content"=>"ioo"}, "commit"=>"Post", "utf8"=>"✓", "authenticity_token"=>"/y8Lr+e7xgabt60GWxnMGvCtIi7IjqrYDoA84vAqYcE=", "remotipart_submitted"=>"true", "X-Requested-With"=>"IFrame", "X-Http-Accept"=>"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01"}
[02b23327ad83000f75c418d8739e7f49] [127.0.0.1] User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
[02b23327ad83000f75c418d8739e7f49] [127.0.0.1] Completed 500 Internal Server Error in 649ms
[02b23327ad83000f75c418d8739e7f49] [127.0.0.1]
ActiveModel::MassAssignmentSecurity::Error (Can't mass-assign protected attributes: photo):
app/controllers/microposts_controller.rb:9:in `create'
After changing the attr_accessor back to :photo instead of :photo_attributes:
Started POST "/microposts" for 127.0.0.1 at 2012-05-10 21:20:07 +0100
[985e0f204bf7ffac1f7c02fbec35ad9b] [127.0.0.1] Processing by MicropostsController#create as JS
[985e0f204bf7ffac1f7c02fbec35ad9b] [127.0.0.1] Parameters: {"micropost"=>{"photo"=>{"image"=>#<ActionDispatch::Http::UploadedFile:0x00000102f8a3b0 #original_filename="7seriesbmw.png", #content_type="image/png", #headers="Content-Disposition: form-data; name=\"micropost[photo][image]\"; filename=\"7seriesbmw.png\"\r\nContent-Type: image/png\r\n", #tempfile=#<File:/var/folders/fh/fhADKPjGG8qSuCeoHCTNYE+++TI/-Tmp-/RackMultipart20120510-15197-9rt2xn>>}, "user_id"=>"2", "content"=>"pp"}, "commit"=>"Post", "utf8"=>"✓", "authenticity_token"=>"/y8Lr+e7xgabt60GWxnMGvCtIi7IjqrYDoA84vAqYcE=", "remotipart_submitted"=>"true", "X-Requested-With"=>"IFrame", "X-Http-Accept"=>"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01"}
[985e0f204bf7ffac1f7c02fbec35ad9b] [127.0.0.1] User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
[985e0f204bf7ffac1f7c02fbec35ad9b] [127.0.0.1] Completed 500 Internal Server Error in 452ms
[985e0f204bf7ffac1f7c02fbec35ad9b] [127.0.0.1]
ActiveRecord::AssociationTypeMismatch (Photo(#2180069640) expected, got ActiveSupport::HashWithIndifferentAccess(#2153916820)):
app/controllers/microposts_controller.rb:9:in `create'
Microposts controller create action:
def create
if params[:micropost][:user_id].to_i == current_user.id
#micropost = current_user.microposts.build(params[:micropost])
#comment = Comment.new(:user_id => current_user.id)
respond_to do |format|
if #micropost.save
format.js { render :post_on_springboard }
end
end
else
user = User.find_by_username(params[:micropost][:username])
#micropost = user.microposts.build(params[:micropost])
if #micropost.save
UserMailer.new_wall_post_notification(user, current_user).deliver if user.email_notification == 1
flash[:success] = "Micropost posted"
redirect_to root_path+user.username
else
flash[:error] = "#{#micropost.errors.full_messages.first}"
redirect_to root_path+user.username
end
end
end
A lot of what you are trying to do concerns relationships and you shuld be able to get rails conventions working for you. If you start writing a bunch of code for somehting fairly simple with rails that's usually a bad sign.
I would focus first on your routes actually.
If you nest photo inside albums for instance, e.g.
resources :albums do
resources :photos
end
Then you will get a lot of the paths and functionality that you want.
Make sure your forms use things like form_for [#album, #post] which will go along with your accepts_nested_attributes_for
try adding :photo_attributes to your attar_accessible list in your micropost model
That should resolve the first error, I think.
Still looking into the second.
Can you post the complete stack trace from the form, it might be an issue with your controller mothods.
changing
f.fields_for #photo
to
f.fields_for :photo
and adding
#micropost.build_photo(:photo_album_id => :photo_album_id => current_user.photo_albums.find_by_album_title("microposts album").id)
to my microposts_controller fixed my issue
class Organization < ActiveRecord::Base
has_one :picture, :dependent => :destroy
accepts_nested_attributes_for :picture
attr_accessible :address, :contect_number, :email, :name, :type_of_organization, :picture_attributes
end
class Picture < ActiveRecord::Base
belongs_to :organization
mount_uploader :avatar, AvatarUploader
attr_accessible :avatar, :organization_id
end
class OrganizationsController < ApplicationController
load_and_authorize_resource
def new
#organization = Organization.new
# #organization.attributes = Picture.new
# #picture = Picture.new
end
def create
logger.info "++++++++inside the organisation controller++++++++++"
logger.info params[:organization].inspect
#org = Organization.new(params[:organization])
if #org.save
#picture = Picture.new(:avatar => params[:organization][:picture_attributes][:avatar])
#picture.organization_id = #org.id
#picture.save
logger.info "---------- inside Avtar controller ---------------"
logger.info #picture.inspect
session[:org_id] = #org.id
redirect_to new_admin_user_path :notice => 'Organization created successfully.'
else
render 'new'
end
end
end
<div>
<h4>FillUp organization details.</h4>
<%= form_for #organization, :url => organizations_path do |f| %>
<%= f.label :name, "Name" %>
<%= f.text_field :name %>
<%= f.label :contect_number, "Contact Number" %>
<%= f.text_field :contect_number %>
<%= f.label :address, "Address" %>
<%= f.text_field :address %>
<%= f.label :website, "Website" %>
<%= f.text_field :email %>
<%= f.label :company_type, "Type" %>
<%= f.text_field :type_of_organization %>
<%= f.fields_for :picture_attributes, :html => { :multipart => true } do |p| %>
<%= p.label :avatar, "My Avatar" %>
<%= p.file_field :avatar %><br/>
<%end%>
<%= f.submit :Create, :class => 'btn btn-primary' %>
<%end%>
</div>
I've searched a lot and the common cause of this problem is attr_ascessible :model_attributes not being declared but I can't seem to get it working.
Looking at the Log below :referee, and :ticket_order values are in the params hash but then are inserted as null in the table. Foreign keys for user_id and event_id are saved in a new record without any errors. The warning about mass assignment led me to the attr_ascessible declaration, tried different variations of it without luck. I'm using devise.
Development log
Started POST "/events/1" for 127.0.0.1 at 2011-07-14 17:38:16 +0100
Processing by EventsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"ddddddjTdnaLKQgZncSDGYt63JA=", "event"=>{"relationship"=>{"event_id"=>"1", "referee"=>"9", "ticket_order"=>"1"}}, "commit"=>"Confirm Purchase", "id"=>"1"}
User Load (20.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 8 LIMIT 1
Event Load (13.1ms) SELECT "events".* FROM "events" WHERE "events"."id" = 1 LIMIT 1
AREL (18.7ms) INSERT INTO "relationships" ("user_id", "event_id", "created_at", "updated_at", "referee", "ticket_order") VALUES (8, 1, '2011-07-14 16:38:16.963351', '2011-07-14 16:38:16.963351', NULL, NULL)
WARNING: Can't mass-assign protected attributes: relationship
[paperclip] Saving attachments.
Redirected to http://localhost:3000/events/1
Completed 302 Found in 588ms
Events
class Event < ActiveRecord::Base
attr_accessible :artist, :venue, :show_info, :date, :doors, :ticket_issue, :ticket_price,
:travel_cost, :accomodation_cost, :hire_cost, :image, :avatar_url, :relationships_attributes, :referee, :ticket_order
has_many :relationships
has_many :users, :through => :relationships
accepts_nested_attributes_for :relationships
Events Controller
def new
#event = Event.new
#users = Relationships.find(:all)
relationship = #event.relationships.build()
end
def create
#event = Event.new(params[:event])
current_user.attend!(#event)
if #event.save
redirect_to #event, :notice => "Successfully created event."
else
render :action => 'new'
end
end
User.rb
def attending?(event)
relationships.find_by_event_id(event)
end
Relationship.rb
class Relationship < ActiveRecord::Base
belongs_to :user
belongs_to :event
attr_accessible :event_id
form view
<%= semantic_form_for #event do |form| %>
<%= form.semantic_fields_for :relationship do |builder| %>
<%= builder.hidden_field :event_id, :value => #event.id %>
<%= builder.inputs do %>
<%= builder.input :referee, :as => :select, :collection => #event.users.all %>
<%= builder.input :ticket_order, :as => :number %>
<% end %>
<% end %>
Yes it must be this, replace:
form.semantic_fields_for :relationship
with:
form.semantic_fields_for :relationships
Update: according to the stack trace, posted at the end of this question, I think the real problem is to figure out what attr_accessible and build association settings I need to get the contributors and linkers attributes to update with the new isbn id. Please help me!
Following on from this question...
I've got a join table between two models - isbns and contributors - which have a many to many relationship. I want to use the existing values from the contributor model in a collection_select drop-down, within a nested form using fields_for.
So when I'm creating a new isbn, I don't want to create new contributor records - I want to be able to select existing ones. And I want to be able to select many contributors, which is why I'm using the nested_form gem which allows me to dynamically create additional form fields for contributors.
My question: should I be calling the method on the join table? And if so, why do I get a 'missing block' error despite having pretty much everything attr_accessible and accepts_nested_attributes_for:
isbn.rb:
attr_accessible :linkers_attributes, :contributors_attributes, :contributor_id,
has_many :linkers
has_many :contributors, :through => :linkers
accepts_nested_attributes_for :contributors
accepts_nested_attributes_for :linkers
contributor.rb:
attr_accessible :linkers_attributes, :isbns_attributes
has_many :linkers
has_many :isbns, :through => :linkers
accepts_nested_attributes_for :isbns
accepts_nested_attributes_for :linkers
linker.rb:
belongs_to :isbn
belongs_to :contributor
accepts_nested_attributes_for :contributor
accepts_nested_attributes_for :isbn
attr_accessible :isbn_id, :contributor_id, :isbns_attributes, :contributors_attributes, :contributor_attributes, :isbn_attributes
isbns controller:
def new
#isbn = Isbn.new
#title = "Create new ISBN"
1.times {#isbn.linkers.build}
end
new.html.erb:
<td class="main">
<%= nested_form_for #isbn, :validate => false do |f| %>
<h1>Create new ISBN</h1>
<%= render 'shared/error_messages', :object => f.object %>
<%= render 'fields', :f => f %>
<div class="actions">
<%= f.submit "Create" %>
</div>
_fields: (option 1)
<%= f.fields_for :contributors do |contributor_form| %>
<li>
<%= contributor_form.label 'Contributor Name' %>
<%= contributor_form.collection_select(:isbn_id, Contributor.all, :id, :personnameinverted ) %>
</li>
<%= contributor_form.link_to_remove "[-] Remove this contributor"%>
<% end %>
<%= f.link_to_add "[+] Add a contributor", :contributors %>
This creates a new ISBN, and a new record in linkers with the correct isbn_id, but also a new record in contributors, when I actually want the new linker record to contain an existing contributor_id. So I figured I'd do this:
_fields (option 2)
<%= field_set_tag 'Contributor' do %>
<li>
<%= f.label 'Contributor Sequence Number' %>
<%= f.text_field :descriptivedetail_contributor_sequencenumber%>
<%= tooltip(:xxx, :hover) %>
</li>
<%= f.fields_for :linkers do |contributor_form| %>
<li>
<%= contributor_form.label 'Contributor Name' %>
<%= contributor_form.collection_select(:isbn_id, Contributor.all, :id, :personnameinverted ) %>
</li>
<%= contributor_form.link_to_remove "[-] Remove this contributor"%>
<% end %>
<%= f.link_to_add "[+] Add a contributor", :contributors %>
But this returns a missing block error.
Huge thanks in advance, I've spent two solid days on this and think I might pop.
update: Here's a clue, the stack trace from this new code, because I figured you can't actually call a method on a join table:
<%= f.fields_for :contributors do |contributor_form| %>
<li>
<%= contributor_form.collection_select(:id, Contributor.all, :id, :personnameinverted, :include_blank => true ) %>
Started POST "/isbns" for 127.0.0.1 at 2011-06-08 20:12:48 +0100
Processing by IsbnsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"u0TszLESOnZlr4iEiBlVg6w9B5T+EH0dxJg/0E6PKuQ=", "isbn"=>{"descriptivedetail_titledetail_titleelement_titleprefix"=>"", "descriptivedetail_titledetail_titleelement_titlewithoutprefix"=>"qqq", "istc_id"=>"471", "descriptivedetail_contributor_sequencenumber"=>"", "contributors_attributes"=>{"0"=>{"id"=>"1", "_destroy"=>"false"}, "1307560328932"=>{"id"=>"14", "_destroy"=>"false"}}, "descriptivedetail_contributor_contributorrole"=>""}, "commit"=>"Create"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 2 LIMIT 1
Contributor Load (0.3ms) SELECT "contributors".* FROM "contributors" INNER JOIN "linkers" ON "contributors".id = "linkers".contributor_id WHERE "contributors"."id" IN (1, 14) AND (("linkers".isbn_id = NULL))
Completed in 308ms
So it looks like the contributor IDs are actually being set, but the linker table isn't being passed the isbn id. Onwards...
Well. Here's how I did it.
Installed cocoon gem.
Finally got round to installing Haml, too,
I split out the new and update action, so the new form is just a quickie to get the id set, with the bare minimum of fields. Then users can edit it, and add contributors. Not actually bad from the user point of view as they can create an isbn quickly without having to fill in a bazillion fields.
isbns/new.html.haml
%td.main
= semantic_form_for #isbn do |f|
%h1 Create new ISBN
= render 'shared/error_messages', :object => f.object
= render 'fields', :f => f
%div#actions
= f.submit "Create"
isbns/_fields.html.haml
- f.inputs do
= f.input :istc_id, :as => :select, :collection => Istc.all
= f.input :descriptivedetail_titledetail_titleelement_titlewithoutprefix
%h3 Contributors
#tasks
= f.semantic_fields_for :linkers do |linker|
= render 'linker_fields', :f => linker
.links
= link_to_add_association 'add contributor', f, :linkers
-f.buttons do
= f.submit 'Save'
isbns/_linker_fields.html.haml
.nested-fields
= f.inputs do
= f.input :contributor_id, :label_method => :keynames, :as => :select, :collection => Contributor.all
= link_to_remove_association "remove contributor", f
Isbn.rb
has_many :linkers
has_many :contributors, :through => :linkers
accepts_nested_attributes_for :contributors, :allow_destroy => true
accepts_nested_attributes_for :linkers, :allow_destroy => true
contributor.rb
attr_accessible :linkers_attributes, :isbns_attributes
has_many :isbns, :through => :linkers
has_many :linkers
accepts_nested_attributes_for :linkers
linker.rb
belongs_to :contributor
belongs_to :isbn
accepts_nested_attributes_for :contributor
Results in
Started POST "/isbns/58" for 127.0.0.1 at 2011-06-09 12:34:14 +0100
Processing by IsbnsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"u0TszLESOnZlr4iEiBlVg6w9B5T+EH0dxJg/0E6PKuQ=", "isbn"=>{"istc_id"=>"360", "descriptivedetail_titledetail_titleelement_titlewithoutprefix"=>"thurs title", "linkers_attributes"=>{"0"=>{"contributor_id"=>"3", "_destroy"=>"", "id"=>"68"}, "1"=>{"contributor_id"=>"71", "_destroy"=>"", "id"=>"69"}, "2"=>{"contributor_id"=>"72", "_destroy"=>"", "id"=>"70"}, "3"=>{"contributor_id"=>"3", "_destroy"=>"", "id"=>"71"}}}, "commit"=>"Save", "id"=>"58"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 2 LIMIT 1
Isbn Load (8.2ms) SELECT "isbns".* FROM "isbns" WHERE "isbns"."id" = 58 ORDER BY descriptivedetail_titledetail_titleelement_titlewithoutprefix LIMIT 1
Linker Load (0.3ms) SELECT "linkers".* FROM "linkers" WHERE "linkers"."id" IN (68, 69, 70, 71) AND ("linkers".isbn_id = 58)
AREL (0.4ms) UPDATE "linkers" SET "contributor_id" = 3, "updated_at" = '2011-06-09 11:34:14.509943' WHERE "linkers"."id" = 71
Contributor Load (158.3ms) SELECT "contributors".* FROM "contributors"
Redirected to http://localhost:3000/isbns/58
Completed 302 Found in 545ms
In other words, from an isbn edit form which has dynamically produced nested fields_for, using formtastic, I can use a drop down menu to select an existing contributor which has a many to many relationship with isbns.
Phew.
I'm having difficulty saving two fields in a nested form. The parent field saves fine, but the nested field is throwing the "WARNING: Can't mass-assign protected attributes" error.
I've placed things in the Item model with attr_accessible, but it's not solving the issue.
List_controller
def create
#list = List.new(params[:list])
#list[:user_id] = current_user.id
if #list.save
flash[:notice] = "Successfully created list."
redirect_to #list
else
render :action => 'new'
end
end
List model
class List < ActiveRecord::Base
has_many :items, :dependent => :destroy
accepts_nested_attributes_for :items, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true
end
Item model
class Item < ActiveRecord::Base
belongs_to :list
end
Form
<%= form_for(#list) do |list_form| %>
<p>
<%= list_form.label :title %><br />
<%= list_form.text_field :title %>
</p>
<p>
<%= render :partial => 'item_fields',
:locals => {:form => list_form} %>
</p>
<%= list_form.submit %>
<% end %>
Form partial
<%= form.fields_for :item do |item_form| %>
<%= item_form.label :name, 'item' %>
<%= item_form.text_field :name %>
<% end %>
Server error log
Started POST "/lists" for 127.0.0.1 at Sun Mar 27 02:54:18 -0400 2011
Processing by ListsController#create as HTML
Parameters: {"commit"=>"Create List", "list"=>{"title"=>"figaro", "item"=>{"na
me"=>"foobar"}}, "authenticity_token"=>"afu5xPgvJenu6XKXcsyilR8RconLP/OZ3NxsICE3RVk=
", "utf8"=>"Γ£ô"}
←[1m←[35mUser Load (1.0ms)←[0m SELECT "users".* FROM "users" WHERE "users"."i
d" = 2 LIMIT 1
WARNING: Can't mass-assign protected attributes: item
←[1m←[36mAREL (2.0ms)←[0m ←[1mINSERT INTO "lists" ("user_id", "updated_at", "
title", "created_at") VALUES (2, '2011-03-27 06:54:18.893302', 'figaro', '2011-0
3-27 06:54:18.893302')←[0m
Redirected to http://localhost:3000/lists/77
Completed 302 Found in 117ms
You're using fields_for :item but your List model has_many :items.
Try this:
<%= form.fields_for :items do |item_form| %>
If this doesn't help try to add attr_accessible :items_attributes to you List model. From the docs:
[..] If you are using attr_protected or attr_accessible, then you will need to add the attribute writer to the allowed list.
Add attr_accessible :items to your List class.