#17 HABTM Checkboxes (revised)
A many-to-many association can be edited through check boxes in a form. Here I show how to do this with a has_many through association complete with clickable labels.
- Download:
- source code
- mp4
- m4v
- webm
- ogv
I literally did this yesterday. I will finally subscribe just to see if we did it the same way.
Thanks for subscribing!
yes it worth it, thanks ryan for your contribution and waiting of the refactoring of the episode "multi-step forms".
I wish you all the best
Rash
I agree. Multi Steps Forms re-factored would be nice. BUMP :-)
Me too!!
I would love to see a wizard episode + the integration of a "Devise registration step" in order to see how to customize Devise with this and how to create a multi-steps form with multiple forms.
Thanks!
+1
+1
Hey Ryan, Merry Xmas from a Rails noob. This and Autocomplete revised was the two episodes that made me decide to subscribe too.
Just wanted to let you know your railscasts was the thing that really cleared up my RoR concepts, it's just awesome visual learning by example. Thanks!
Subscribing is totally worth it. I swear that last night I was literally looking on how to do this in Rails. Then bam. Next day here it is.
Using the hidden tag set to
nil
didn't work in my rails project. It might have to do with the fact that I'm using the Mongoid ODM. I found that unless all the values in the array are valid ids, nothing will change. (I suspect that ActiveRecord just ignores any non-valid values.)To combat this issue, I set my hidden tag to a string like 'included'. Then in the controller, I used the line
I'm not sure if this is the best solution, but it works.
wow , i didnt know about dom_id, you know how many places have used interpolation instead?... :(
=D good thing i learned this , thanks Ryan.
How about following up with a series of screen-casts using Simple Form gem? I have used it in the past and the current project and find it extremely useful. Moreover, the PlataformaTec crew manning the Google Group is super helpful. I think a set of "Professional Screencasts" on Simple forms where you go deeper into the subject matter just as you did with z-shell will be very useful.
This screencast was great. Keep up the good work.
Bharat
Second that.
Instead using
<%= hidden_field_tag "product[category_ids][]", nil %>
i used in my controller update action something like this:This works fine too! :)
When I use radios and checkboxes I generally wrap the input and text in a label tag. I like it because it increases the clickable area for a more comfortable UX. (http://dabblet.com/gist/1515022)
+1
It's amazing how much I learned from this episode, for instance, I had no idea why we were submitting the hidden field for checkboxes; I also totally forgot about the dom_id method, and have been hacking id's together. I think I have some refactoring to do.
Thanks Ryan for an awesome year of Railcasts. Happy Holidays and all the best for the New Year!
Thanks for the amazing material. At $10 a month this is the most valuable development resource I've come across.
If anyone is having trouble getting the checkboxes to save make sure you make your assocation_ids accessible.
In my controller I have to add "@product.category_ids = params[:product][:category_ids]" to the create and update actions, otherwise nothing gets stored in the database. I don't see this in the source code of this episode. Am I forgetting something?
verify that you can access the category_id column via mass assignment.
Add category_id to the attr_accessible declaration in your model
Thanks, that worked.
I'd like to see an example where categories and products are scoped through a current user. I'm trying to modify this example to scope things through a current_user and just can't seem to get it to work.
For example, in the form, I have:
and in the controller, I have:
The correct list of products is displayed on the form, but the save fails...
Just as a follow up, I traced my problem to the user_id not being included in the join table, which was causing a validation failure. So I need to figure out how to pass the user_id to the join table (categorizations). I'm kind of stumped because the join table entries are being created behind the scenes, so to speak (i.e., I don't have an explicit statement saving those). Any help would be greatly appreciated.
Is it actually safe to allow mass-assignment in this context?
Subscribed just for this episode so I do this the best way. Thanks!
I'm placing a comment onto this episode as it seems the most relevant.
Has anyone done a good example on the use of rails has_and_belongs_to_many, as i cannot think of a scenario in which i do not use has_many through: and i just cannot get my head around the habtm function...
I'm thinking about using HABTM instead of has_many because in my case, I do have a catalog of names (contributors) linked to a "groups" table.
Each "group" may have many "contributors" and each "contributor" may belong-to-many "groups". These two tables are linked with a "memberships" table.
As I don't want to waste my time with views, model, controller, routes, callbacks, bla-bla-bla for the "memberships" table, I just want to be able to set many contributors belonging to my group on my group form with a select-box. That is far more quicker to use the HABTM. (Now for validation, I just put a SQL table constraint UNIQUE index on both ID column of the membership table (in my migration) to avoid creating multiple same membership. This a protection against pirates, because a select box doesn't allow you to select multiple times the same item)
I think HABTM still make sens when you need to link one of your tables with a table (with a single column/attribute) that is just used as catalog of values. I may be wrong, but it makes sens to me.
Rails Guides have a short comment on this: http://guides.rubyonrails.org/association_basics.html#choosing-between-has-many-through-and-has-and-belongs-to-many
As usual, this is a very handy example. However, I'm a bit confused. Why don't we need to use the "accept_nested_attributes_for" class method ?
I have the same question...does anyone know the answer?
Very helpful screencast. Thanks!
Thanks for this great screencast.
Got an issue with my app.
Checkboxes well diplayed, but when I update, got a message "Can't mass-assign protected attributes: group_ids"
So, I try to manage membership.
Got users and groups.
membership model :
User model :
Group model
Here the code in my form
Did I miss something ?
Thanks
Very late but someone may benefit from this.
You need to add :group_ids to your user model:
Ok adding group_ids as attr_accessible in my User Model solve the problem !
Sorry :p
Exactly what I needed, subscribed to gain access to the revised versions, first for Revised 88 and now this one. Thank you so much!
Is there a way to display a text field when a checkbox is checked? Say you want to add more info about that product in the join model. You check "Board Game" and you want to comment that "Settlers of Catan is a great Board Game for ages 5 - Adult" (or something like that). You also check "Toys & Games" and want to add "A Great Christmas Gift". This would update a field in the join model table called "Comments". The data in the join model would now be
ID 1
product_id 1
category_id 1
comment "Settlers of Catan..."
ID 2
product_id 1
category_id 6
comment "A Great Christmas ..."
My question is, how do you store extra info in the join model and extract that out later?
Thanks.
Martin, I want to do something similar. Did you find a solution?
Did you find a solution for this? Looking for the same.
Hi
Could you please share how you solved it? I have the same problem ie save additional field in join table.
Thanks
With Rails 4 and strong parameters, if we want this to work, we have to add
resource_ids: []
in the permit call. For example :Am I right? It doesn't work if we just add :role_ids in the permit call, because it's an array and not a scalar.
@Antoine You might want to try the following...
as this is what worked for me.
Both methods of setting hash values work the same, it's a matter of style preference.
Thanks so much! This definitely helped me out as well.
Thanks, after banging my head on the wall for too long this saved me! :)
Have you tried for model for devise gem. I am not able to save it.
Thanks for pointing this out, it helped me get this working in Rails 4.
Just ran into this myself. Should've read the comments before I plunged into the StrongParameters docs. Oh well.
I'm curious if this is the "right" approach for me to use for a particular portion of my application.
I have many tasks and many users. Tasks belong to a particular user, but can be completed by multiple users (defined by a manager role over another model).
Anyway, I want users to be able to opt-in/out of being reminded about certain tasks that they either own or manage.
My thought is to do a has_many :through relationship with a reminder join table.
My interface differs from the one in this railscast in that in the presentation of a task list, there would be just a single check box for each task that determines whether the current logged in user will get reminders for the task.
So I see lots of parallels to this railscast, but I can't seem to get to solution that doesn't feel cludgy. Am I on the right path?
Thanks!
'YAY THAT WORKS' - loving it! :)
Very helpful screencast! There are several Rails 4 helper methods for this and similar form building: https://github.com/rails/rails/blob/master/actionview/lib/action_view/helpers/form_options_helper.rb
Though doing it using Ryan's way allows for infinite flexibility.
Hi all,
I am trying to reproduce this approach using simple_form, but I am not sure how to recreate the check boxes using simple_form with all the features Ryan covered in this screencast.
Has anyone done this earlier?
Appreciate the help.
Xiao
I'm using Ruby 2.0 and Rails 3.2.8 and I can't seem to get the simple has_many through part working.
In my Event model
In my Eventcategory model
In my Categorization model
The tables are all there for all three models.
When I run:
e = Event.first
in the console it gets me my first event.Then I run:
e.eventcategory_ids
I get:NoMethodError: undefined method 'eventcategory_ids' for #<Event:0x00000002b7d660>
I figure that has to work before any of the rest of the stuff from this screencast will work for me... right? Am I missing something here?
OK, I fixed it by changing all my eventcategory stuff over to eventcat to keep the naming less likely to get mixed up.
Not sure when Rails added this, but there's a much simpler way now:
<%= f.collection_check_boxes :category_ids, Category.all, :id, :name %>
Only valid since Rails v4.0.2
Thanks Michael
Thanks so much! Wonderful pretty simple example!
amazing!
Friggin sweet.
I have error:
> ActiveRecord::RecordNotFound in UsersController#update
> Couldn't find all CategoryUsers with IDs (1, 3) (found 0 results, but was looking for 2)
Help me pleace
I have an odd case where my code created with the help of this rails casts for HABTM checkboxes was working fine... an then all of a sudden I'm getting a NoMethodError: undefined method `name' for nil:NilClass error when creating or updating a record that has project_ids filled in.
If I try to use the method in the rails console I get the error specifically at the point of adding project_id's like this:
p = Project.last
works and returns project field data
p.person_ids = [1,2]
And the weird part is, that once that all happens, if I call p.save after the errors list, it actually saves properly adding the two people assignments to the project
I've rolled back the git history to see if I did something else, but even if I go way back to previous versions that worked for sure it still gives the same error. This makes me think it's database related??
I have been trying to model a similar domain, but the price has to be on the join table, since the price is not known until purchased (think auction). I have read every post on the internet pertaining to has_many through with additional attributes on the join table and I am still not getting it.
I forked the repo https://github.com/jamlevi/017-habtm-checkboxes-revised and added a new folder "store-move-price-to-join". I added views/categories & controllers/categories_controller.rb. Using rails 3.2.17.
I realize this page/thread are pretty old, but I am hoping somebody out there sees this and can help me out (plus the same question is unanswered from 2 years ago). Pretty sure I need a fields_for in views/categories/_form.html & accepts_nested_attributes_for in category. A working repo would be tremendously helpful, instead of code snippets buried in many similar-but-not-same use case posts scattered throughout the intenet.
Hey there @jamlevi, I recently wrote up an article about this based on your question at:
http://ducktypelabs.com/how-to-use-has_many-through-with-additional-attributes-on-the-join-table/
You're on the right path with
fields_for
andaccepts_nested_attributes_for
.I did also include an example repo on GitHub for reference and to play around with. If the use case in the article doesn't match what you're looking for, be sure to let me know in the comments section and I'll try to help out, cheers!
Sid