Ceres wrote:check_box_tag 'expense[tag_ids][]', tag.id, @expense.tags.include?(tag)
1. I think I understand why you are doing expense[tag_ids][], but I don't understand why it works. What is Rails doing within that statement and what is it looking for that makes this special naming work?
Rails treats square brackets in form field names a special way. If there's text between the square brackets Rails will put the value inside a hash. If there's no text inside the square brackets Rails will gather all the values with that name and put them into an Array.
For example, we end up with several checkboxes with the name "expense[tag_ids][]". If you take a look at the development log when you submit the form you will see how Rails splits this up. Something like this:
Parameters: {"action" => "create", "controller" => "expenses", { "expense" => { "name" => "foo", "tag_ids" => ["1", "3", "8"] }}}You can see this is an array of numbers (checked tag ids) inside a hash which is inside another hash. This all gets thrown into the "params" hash which you use in the create/update actions in the controller.
@expense = Expense.new(params[:expense])
If you look back at the parameters you can see the parmas[:expense] is actually a hash. So this is what it's doing:
@expense = Expense.new("name" => "foo", "tag_ids" => ["1", "3", "8"])When you supply a hash to the "new" method like this, it will set the attributes of Expense. This ends up calling each method:
expense.name = "foo"
expense.tag_ids = ["1", "3", "8"]
This tag_ids method is something that is added when you set the has_and_belongs_to_many association. It basically sets which tags the expense belongs to.
Ceres wrote:2. @expense.tags.include?(tag) - What is going on here?
It may help to break it up. The @expense.tags method returns an array of tag models that the expense is related to. The "include?" method is defined in Array and returns true/false depending on if the given parameter is inside the array. In other words, this returns true if the expense has that tag, and false if it doesn't. The result is a checked or unchecked checkbox.
Railscasts - Free Ruby on Rails Screencasts