Using a multi select input control to manage a one-to-many relationship in Rails is not hard, but it also was not obvious to me when I first tried to do it.
Have two models that are related as so:
class ControlGroup < ActiveRecord::Base
has_many :control_group_rate_addresses
has_many :rate_addresses, :through => :control_group_rate_addresses
end
class RateAddress < ActiveRecord::Base
has_many :control_group_rate_addresses
has_many :control_groups, :through => :control_group_rate_addresses
end
class ControlGroupRateAddress < ActiveRecord::Base
belongs_to :control_group
belongs_to :rate_address
end
And a fragment of controller code in ControlGroupsController:
Along with an html fragment of:
The part that I didn't get immediately was the ":rate_address_ids" method call.
I also have ajax interaction with this controller that needs to know what items have been selected and make a call back to the server when the multi-select input control changes. I use jquery, but you could do this (although it would be more verbose) without it. The relevent lines are:
Building the array of selected RateAddress id's was pretty easy using jquery's powerful selectors.
Then I just had to append the [] in the get call to ensure that the parameters came through as an array.
Back in the controller I can just look at the params and pull out the selected rate_addresses and do whatever I wish.
Hope this helps someone else through this little frustration I had.
Have two models that are related as so:
class ControlGroup < ActiveRecord::Base
has_many :control_group_rate_addresses
has_many :rate_addresses, :through => :control_group_rate_addresses
end
class RateAddress < ActiveRecord::Base
has_many :control_group_rate_addresses
has_many :control_groups, :through => :control_group_rate_addresses
end
class ControlGroupRateAddress < ActiveRecord::Base
belongs_to :control_group
belongs_to :rate_address
end
And a fragment of controller code in ControlGroupsController:
def edit
@control_group = ControlGroup.find(params[:id])
@all_rate_addresses = RateAddress.all
end
@control_group = ControlGroup.find(params[:id])
@all_rate_addresses = RateAddress.all
end
Along with an html fragment of:
<%= f.label :rate_address_id %>
<%= collection_select(:control_group, :rate_address_ids, @all_rate_addresses, :id, :name, {}, :multiple => true) %>
<%= collection_select(:control_group, :rate_address_ids, @all_rate_addresses, :id, :name, {}, :multiple => true) %>
The part that I didn't get immediately was the ":rate_address_ids" method call.
I also have ajax interaction with this controller that needs to know what items have been selected and make a call back to the server when the multi-select input control changes. I use jquery, but you could do this (although it would be more verbose) without it. The relevent lines are:
var rate_addresses = $.map($("#control_group_rate_address_ids option[selected]"),
function(value) { return $(value).attr('value') });
$.get(device_url(node_id), { "rate_address_ids[]": rate_addresses },
function(data){
$("#device-list-container").html(data);
});
function(value) { return $(value).attr('value') });
$.get(device_url(node_id), { "rate_address_ids[]": rate_addresses },
function(data){
$("#device-list-container").html(data);
});
Building the array of selected RateAddress id's was pretty easy using jquery's powerful selectors.
Then I just had to append the [] in the get call to ensure that the parameters came through as an array.
Back in the controller I can just look at the params and pull out the selected rate_addresses and do whatever I wish.
Hope this helps someone else through this little frustration I had.