Topic: Error sending HABTM parameters

I am trying to implement a has_and_belongs_to_many checkbox page but my application is dying when trying to parse the parameters (i.e. before it hits the "update" action).  My view:

<% form_for @user, :url => { :action => "update_activity" } do |f| %>
  <% for activity in Activity.find(:all) %>
    <div>
      <%= check_box_tag "user[activity_ids][]", activity.id, @user.activities.include?(activity) %>
      <%= activity.activity %>
    </div>
  <% end %>
  <%= f.submit "Update" %>
<% end %>

will give me the "Something went wrong" splash page with the following in the log:

Processing ApplicationController#update_activity (for 127.0.0.1 at 2009-11-09 21:08:58) [PUT]
/!\ FAILSAFE /!\  2009-11-09 21:08:58 -0500
  Status: 500 Internal Server Error
  undefined method `each' for "4":String
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/base.rb:489:in `block in filter_parameter_logging'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/base.rb:496:in `block (3 levels) in filter_parameter_logging'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/base.rb:495:in `collect'
   ...

where "4" happens to be the value of the checkbox (or the first checkbox) that I had selected.  Some Googling told me that it might have something to do with the instance of the user I've loaded from the db, but I'm not convinced it's the story here.  I do have the join tables built also.

Any help?

Thanks,

Andrew

Re: Error sending HABTM parameters

Do you have a full stack trace?

What are the params in this instance?

Re: Error sending HABTM parameters

Here is the full stack trace:

Processing UserController#update_activity (for 127.0.0.1 at 2009-11-09 21:08:58) [PUT]


Processing ApplicationController#update_activity (for 127.0.0.1 at 2009-11-09 21:08:58) [PUT]
/!\ FAILSAFE /!\  2009-11-09 21:08:58 -0500
  Status: 500 Internal Server Error
  undefined method `each' for "4":String
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/base.rb:489:in `block in filter_parameter_logging'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/base.rb:496:in `block (3 levels) in filter_parameter_logging'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/base.rb:495:in `collect'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/base.rb:495:in `block (2 levels) in filter_parameter_logging'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/base.rb:489:in `each'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/base.rb:489:in `block in filter_parameter_logging'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/base.rb:493:in `block (2 levels) in filter_parameter_logging'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/base.rb:489:in `each'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/base.rb:489:in `block in filter_parameter_logging'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/base.rb:1315:in `log_processing_for_parameters'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/base.rb:1302:in `log_processing'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/base.rb:526:in `process'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/filters.rb:606:in `process_with_filters'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/rescue.rb:65:in `call_with_exception'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/dispatcher.rb:91:in `rescue in dispatch'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/dispatcher.rb:97:in `dispatch'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/dispatcher.rb:111:in `_call'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/dispatcher.rb:82:in `block in initialize'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/activerecord-2.3.3/lib/active_record/query_cache.rb:29:in `call'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/activerecord-2.3.3/lib/active_record/query_cache.rb:29:in `block in call'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/activerecord-2.3.3/lib/active_record/connection_adapters/abstract/query_cache.rb:34:in `cache'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/activerecord-2.3.3/lib/active_record/query_cache.rb:9:in `cache'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/activerecord-2.3.3/lib/active_record/query_cache.rb:28:in `call'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/activerecord-2.3.3/lib/active_record/connection_adapters/abstract/connection_pool.rb:361:in `call'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/rack-1.0.1/lib/rack/head.rb:9:in `call'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/rack-1.0.1/lib/rack/methodoverride.rb:24:in `call'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/params_parser.rb:15:in `call'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/session/cookie_store.rb:93:in `call'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/reloader.rb:29:in `call'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/failsafe.rb:26:in `call'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/rack-1.0.1/lib/rack/lock.rb:11:in `block in call'
    <internal:prelude>:8:in `synchronize'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/rack-1.0.1/lib/rack/lock.rb:11:in `call'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/actionpack-2.3.3/lib/action_controller/dispatcher.rb:106:in `call'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/rails-2.3.3/lib/rails/rack/static.rb:31:in `call'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/rack-1.0.1/lib/rack/urlmap.rb:46:in `block in call'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/rack-1.0.1/lib/rack/urlmap.rb:40:in `each'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/rack-1.0.1/lib/rack/urlmap.rb:40:in `call'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/rails-2.3.3/lib/rails/rack/log_tailer.rb:17:in `call'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/rack-1.0.1/lib/rack/content_length.rb:13:in `call'
    C:/Ruby19/lib/ruby/gems/1.9.1/gems/rack-1.0.1/lib/rack/handler/webrick.rb:50:in `service'
    C:/Ruby19/lib/ruby/1.9.1/webrick/httpserver.rb:111:in `service'
    C:/Ruby19/lib/ruby/1.9.1/webrick/httpserver.rb:70:in `run'
    C:/Ruby19/lib/ruby/1.9.1/webrick/server.rb:183:in `block in start_thread'

and here is the request immediately before that (i.e. when it is rendering the checkbox list and checking to see which activities should be selected):

Processing UserController#activity (for 127.0.0.1 at 2009-11-09 21:08:55) [GET]
  Parameters: {"controller"=>"user", "action"=>"activity"}
  User Load (1.0ms)   SELECT * FROM "users" WHERE ("users"."id" = '2') LIMIT 1
  User Update (3.0ms)   UPDATE "users" SET "last_request_at" = '2009-11-10 02:08:55', "updated_at" = '2009-11-10 02:08:55' WHERE "id" = 2
Rendering template within layouts/application
Rendering user/activity
  Activity Load (1.0ms)   SELECT * FROM "activities" 
  Activity Load (0.0ms)   SELECT "activities".id FROM "activities" INNER JOIN "activities_users" ON "activities".id = "activities_users".activity_id WHERE ("activities"."id" = 1) AND ("activities_users".user_id = 2 ) LIMIT 1
  Activity Load (1.0ms)   SELECT "activities".id FROM "activities" INNER JOIN "activities_users" ON "activities".id = "activities_users".activity_id WHERE ("activities"."id" = 2) AND ("activities_users".user_id = 2 ) LIMIT 1
  Activity Load (0.0ms)   SELECT "activities".id FROM "activities" INNER JOIN "activities_users" ON "activities".id = "activities_users".activity_id WHERE ("activities"."id" = 3) AND ("activities_users".user_id = 2 ) LIMIT 1
  Activity Load (0.0ms)   SELECT "activities".id FROM "activities" INNER JOIN "activities_users" ON "activities".id = "activities_users".activity_id WHERE ("activities"."id" = 4) AND ("activities_users".user_id = 2 ) LIMIT 1
  Activity Load (0.0ms)   SELECT "activities".id FROM "activities" INNER JOIN "activities_users" ON "activities".id = "activities_users".activity_id WHERE ("activities"."id" = 5) AND ("activities_users".user_id = 2 ) LIMIT 1
  Activity Load (0.0ms)   SELECT "activities".id FROM "activities" INNER JOIN "activities_users" ON "activities".id = "activities_users".activity_id WHERE ("activities"."id" = 6) AND ("activities_users".user_id = 2 ) LIMIT 1
Completed in 98ms (View: 28, DB: 6) | 200 OK [http://localhost/user/activity]

which seems to be working properly.  The way I have all this set up is that this is a separate page to update the activities so at this point the user has already been created.  I'm only trying to pass the user[activity_ids][] array here, which means that the rendered html looks like this:

<div>
      <input id="user_activity_ids_" name="user[activity_ids][]" type="checkbox" value="2" />
      Subscribe to literary magazines
    </div>

  
    <div>
      <input id="user_activity_ids_" name="user[activity_ids][]" type="checkbox" value="3" />
      Member of a book club
    </div>

and it would seem there's a problem with passing the parameters because even if I try to change the action such that it ONLY renders the parameters I receive it still comes up with the same error, i.e. the parameters are messed up before the update action can really assume control.

Thanks,

Andrew

Re: Error sending HABTM parameters

I think I would put loggers throughout the actionpack code, restart the serer and see what information I can get.

you might have to set logger first
logger = Logger.new(STDERR)

then
logger.error "params are:"
logger.error params.inspect

maybe the params are not built at this time, but you could at least find out why it is looking at 4 and not [4].

What does your view code look like?

Re: Error sending HABTM parameters

I'll try and get the logger into actionpack, I assume just put it immediately around where the error is being thrown?

My view is pretty simple.  I have an already-saved user and this will be a separate page to select the checkboxes for the user's activities, which are stored in a db table:

<% form_for @user, :url => { :action => "update_activity" } do |f| %>
  <% for activity in Activity.find(:all) %>
    <div>
      <%= check_box_tag "user[activity_ids][]", activity.id, @user.activities.include?(activity) %>
      <%= activity.activity %>
    </div>
  <% end %>
  <%= f.submit "Update" %>
<% end %>

I have the activities_user model and the activities_users db tables set up as well.

Re: Error sending HABTM parameters

Duketime wrote:

I'll try and get the logger into actionpack, I assume just put it immediately around where the error is being thrown?

What you have looks correct.  We will want to take a look at what the params look like before the error is being thrown.

Re: Error sending HABTM parameters

Hey, thanks for all the help with this.  I put the logger code into ActionPack, in the filter_parameter_logging method in base.rb, right before the iteration on the unfiltered_parameters (line 489 of actionpack 2.3.3), and I see six log entries for the view I posted earlier (the view only has the HABTM checkbox list).  Those six log entries are the following three lines logged twice:

params are:
{"_method"=>"put", "authenticity_token"=><token>, "user"=>{"activity_ids"=>["3", "5"]}, "commit"=>"Update", "controller"=>"user", "action"=>"update_activity"}
params are:
{"activity_ids"=>["3", "5"]}
params are:
"3"

"3" and "5" refer to the activities that I had selected from the list, and it seems that Action Pack is unpacking the checkbox parameters one level too far, trying to treat just the "3" value as a hash.  I don't see any reason why this would be.  If I submit this particular page without any options checked, the user params array doesn't even get sent.  If I move the checkbox list to the same form used to create / edit a user, I get the same issues when submitting with any items checked, but if I submit without any entries checked it updates "fine" because the activity_ids array isn't in the params list.

Re: Error sending HABTM parameters

ruby 1.9.1?

https://rails.lighthouseapp.com/project … h-ruby-191

They say that String#each is not defined any more in ruby 1.9.1.