I have an application that tracks services (servers) with IP addresses. I'm trying to set it up so that when I create a new service the following happens:
- All IP addresses are looked up, if they do not have a service_id then they're classed as available and returned to a select box on the new service page.
- A user selects one or more IP addresses from the select box, fills in the rest of the required service data then when they hit submit, each IP address is updated with the service_id of the service that was just created. (so that the IP is marked as being taken).
As I understand, I think this should be possible with either nested attributes or virtual attributes... But I am not sure.
I have models like so:
class Service < ActiveRecord::Base
has_many :ips
attr_accessor :service_ips
end
class Ip < ActiveRecord::Base
belongs_to :service
end
Controller like so:
class ServicesController < ApplicationController
def new
@available_ips = Ip.where(:service_id == nil)
end
And a view like so:
<%= form_for(@service) do |f| %>
<%= f.label :service_ips %>
<%= f.collection_select(:service_ips, @available_ips, :id, :address, { }, {:multiple => true, :size => 5}) %>
<%= f.label :hostname %><br />
<%= f.text_field :hostname, :size => 40 %>
<%= f.submit :id => "submit"%>
<% end %>
How do I make it so each selected IP is updated with the newly created service_id?
This isn't really a nested attributes thing, nor do you need virtual attributes. You're just editing a has-many relationship.
Firstly, you probably want to be using the edit/update actions to be RESTful. Read the routing guide.
In your routes.rb:
Then:
You don't need the accessor in your model, the collection is an accessor:
Then in your views/services/edit.html.erb: