How to neatly handle multiple checkboxes with Rails

Discussion in 'Ruby' started by Edgardo Hames, Apr 26, 2005.

  1. This weekend, I have a written my first Rails application to handle
    technical reports at school. The model is very simple, and the only
    part I don't know how to deal with is the association between authors
    and reports.

    Right now, the edit view for the reports has a table with all the
    authors in the database and a checkbox for each one of them. If the
    list of authors grows too big, this part is going to be a bit too
    rough and unusable. How can I handle this "The Rails Way"?

    I thought a very neat solution would be to use an input field like the
    ones GMail has for the address book. Is that difficult to implement
    using Rails and Ajax? Any ideas on how to do that? Are any ActionView
    helpers available to do this? How can I dinamically add more input
    fields (pushing an "add author" button)?

    In case this solution is way too far from being done, how can I handle
    checking and unchecking the different authors in that table on the
    Controller side? What I would need to do is remove the unchecked
    authors and add the checked ones. This involves iterating over the
    collection of authors and checkboxes and compare the previous values
    with the current ones (which may render the code a little bit
    complicated). How do you all usually solve this problem? Is there any
    solution for this available in Ruby?

    Thanks to everyone,
    Ed
    --
    Encontrá a "Tu psicópata favorito" http://tuxmaniac.blogspot.com

    "Tener una amiga en Ginebra es como tener quinotos en almibar o uvas en ron."
    "Programming is like sex... make one mistake, and support it the rest
    of your life."
    "Defeat is an accomplishment not even the best of us could achieve."
    Edgardo Hames, Apr 26, 2005
    #1
    1. Advertising

  2. On Apr 26, 2005, at 1:54 PM, Edgardo Hames wrote:
    > In case this solution is way too far from being done, how can I handle
    > checking and unchecking the different authors in that table on the
    > Controller side? What I would need to do is remove the unchecked
    > authors and add the checked ones. [...] How do you all usually solve
    > this problem?


    The functionality of checkboxes is the same as that of a
    multiple-select field, though the UI is different.

    I have two tables in a habtm relationship; following is the
    (hacked-together) code that I've used (which happens to use selects,
    but which would be easy to modify for checkboxes).

    The short answer is:
    When you are saving, get a list of all the items currently stored for
    the relationship into an array, get the list of all the new items
    desired into a new array, and then do a two-way difference to figure
    out which relationships must be removed and which must be added.


    Here's the relevant parts of my code:

    # POSTGRESQL SCHEMA
    create table roles (
    id serial primary key,
    name varchar(100) not null
    );

    create table acts (
    id serial primary key,
    action_path varchar(100) not null
    );

    create table acts_roles (
    act_id integer references acts on delete cascade,
    role_id integer references roles on delete cascade,
    primary key ( act_id, role_id )
    );


    #FILE app/model/act.rb
    class Act < ActiveRecord::Base
    has_and_belongs_to_many :roles
    end


    #FILE app/model/role.rb
    class Role < ActiveRecord::Base
    has_and_belongs_to_many :acts
    has_and_belongs_to_many :users

    #This really should be done for all habtm, IMO
    def users=( new_array )
    self.remove_users( self.users - new_array )
    self.users << ( new_array - self.users )
    self.users
    end

    #This really should be done for all habtm, IMO
    def acts=( new_array )
    self.remove_acts( self.acts - new_array )
    self.acts << ( new_array - self.acts )
    self.acts
    end
    end


    #FILE app/controllers/role.rb
    class RoleController < ApplicationController
    def edit
    @role = Role.find_by_id @params[ :id ]
    @page_title = "Edit Role '#{@role.name}'"

    @all_actions = Act.find_all.sort_by{ |act| act.action_path }
    @actions_allowed = @role.acts
    end
    def update
    role = Role.find( role_atts["id"] )
    role.acts = @params['role']['acts'].collect{ |id| Act.find id }
    role.save
    end
    end


    #FILE app/views/role/edit.rhtml
    <!-- snip -->
    <fieldset id="actions" class="two_column">
    <legend><strong>Actions</strong> permitted by <%=@role.name%></legend>
    <select name="role[acts][]" multiple="multiple"
    size="<%=select_length%>">
    <%=options_from_collection @all_actions, @role.acts, :action_path %>
    </select>
    </fieldset>


    #FILE app/helpers/application.rb
    module ApplicationHelper

    # Creates a list of HTML option tags based on a collection of model
    instances
    # with the ability to provide a second collection of elements which
    should be selected
    def options_from_collection( all_items, selected, text_method=:name,
    value_method=:id )
    use_include = selected.respond_to?( :include? ) && !selected.is_a?(
    String )

    all_items.inject([]) do |options, element|
    val = element.send( value_method )
    text = element.send( text_method )
    is_selected = use_include ? selected.include?( element ) : val ==
    selected
    if is_selected
    options << "<option value=\"#{html_escape(val.to_s)}\"
    selected=\"selected\">#{html_escape(text.to_s)}</option>"
    else
    options << "<option
    value=\"#{html_escape(val.to_s)}\">#{html_escape(text.to_s)}</option>"
    end
    end.join( "\n" )
    end
    end
    Gavin Kistner, Apr 29, 2005
    #2
    1. Advertising

  3. On 4/29/05, Gavin Kistner <> wrote:
    > On Apr 26, 2005, at 1:54 PM, Edgardo Hames wrote:
    > > In case this solution is way too far from being done, how can I handle
    > > checking and unchecking the different authors in that table on the
    > > Controller side? What I would need to do is remove the unchecked
    > > authors and add the checked ones. [...] How do you all usually solve
    > > this problem?

    >=20
    > The functionality of checkboxes is the same as that of a
    > multiple-select field, though the UI is different.



    Quite a bit, yeah. Gavin, I'm old, so go slow, but you've completely lost =
    me.

    If I iterate over a check_box tag (using a render_partial_collection),
    what I get is something like:

    <input type=3D"checkbox" name=3D"object[method]" value=3D"2"> foo
    <input type=3D"checkbox" name=3D"object[method]" value=3D"3"> bar
    <input type=3D"checkbox" name=3D"object[method]" value=3D"4"> baz
    <input type=3D"checkbox" name=3D"object[method]" value=3D"10"> blurfle
    ...

    but if I select multiple, params has only 1, due to the same key in each on=
    e:

    @params =3D> {object =3D> {method =3D> 2}} (or 3, or 4, or 10, but never
    more than one of those)

    How do I structure the checkbox tag (or can I?) so that I can end up
    with some indication that (ex.) both "foo" and "bar" were checked?
    Michael Campbell, Jun 9, 2005
    #3
  4. Edgardo Hames

    Chris Eidhof Guest

    On Thu, Jun 09, 2005 at 12:43:46PM +0900, Michael Campbell wrote:
    > On 4/29/05, Gavin Kistner <> wrote:
    > If I iterate over a check_box tag (using a render_partial_collection),
    > what I get is something like:


    > <input type="checkbox" name="object[method]" value="2"> foo
    > <input type="checkbox" name="object[method]" value="3"> bar
    > <input type="checkbox" name="object[method]" value="4"> baz
    > <input type="checkbox" name="object[method]" value="10"> blurfle
    > ...


    > but if I select multiple, params has only 1, due to the same key in each one:

    I think the name should be object[method][] or something like that,
    check this out: http://www.eye.cc/fortopic941.html

    --
    Best regards,
    Chris Eidhof
    Chris Eidhof, Jun 9, 2005
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. steve mathers
    Replies:
    15
    Views:
    554
    Utilisateur PC Libre Service
    Feb 3, 2005
  2. steve mathers
    Replies:
    0
    Views:
    298
    steve mathers
    Jan 23, 2005
  3. Guy
    Replies:
    2
    Views:
    348
    Jonathan Mcdougall
    Oct 3, 2003
  4. Guy

    Backup your projects neatly

    Guy, Oct 2, 2003, in forum: C Programming
    Replies:
    19
    Views:
    463
    Peter Shaggy Haywood
    Oct 6, 2003
  5. Andrei D.
    Replies:
    2
    Views:
    378
    Grant Edwards
    Aug 6, 2003
Loading...

Share This Page