Paul Millar
Paul Millar

Reputation: 324

Rails 3 Nested Attributes?

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:

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?

Upvotes: 1

Views: 707

Answers (1)

sj26
sj26

Reputation: 6833

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:

resources :services

Then:

class ServicesController
  def edit
    @service = Service.find(params[:id])
    @available_ips = Ip.where(:service_id => nil)
  end

  def update
    @service = Service.find(params[:id])
    if @service.update_attributes params[:service]
      redirect_to @service
    else
      render :edit
    end
  end
end

You don't need the accessor in your model, the collection is an accessor:

class Service < ActiveRecord::Base
  has_many :ips
end

class Ip < ActiveRecord::Base
  belongs_to :service
end

Then in your views/services/edit.html.erb:

<%= form_for(@service) do |f| %>
  <%= f.label :ips %>
  <%= f.collection_select(:ip_ids, @available_ips + @service.ips, :id, :address, { }, {:multiple => true, :size => 5}) %>

  <%= f.label :hostname %><br />
  <%= f.text_field :hostname, :size => 40 %>

  <%= f.submit :id => "submit" %>
<% end %>

Upvotes: 2

Related Questions