Rails 3 вложенных атрибута?

Я новичок в рельсах, так что на этом мне не хватает... Короче, у меня есть приложение, которое отслеживает сервисы (серверы) с IP-адресами. Я пытаюсь настроить его так, чтобы при создании новой службы происходило следующее:

  • Все IP-адреса просматриваются, если у них нет service_id, они классифицируются как доступные и возвращаются в поле выбора на новой странице сервиса.
  • Пользователь выбирает один или несколько IP-адресов из поля выбора, заполняет остальные необходимые данные службы, а затем, когда они нажимают "Отправить", каждый IP-адрес обновляется с помощью service_id только что созданной службы. (так что IP помечается как занятый).

Как я понимаю, я думаю, что это должно быть возможно либо с вложенными атрибутами, либо с виртуальными атрибутами... Но я не уверен.

У меня есть такие модели:

class Service < ActiveRecord::Base
  has_many :ips
  attr_accessor :service_ips
end

class Ip < ActiveRecord::Base
  belongs_to :service
end

Контроллер вроде так:

 class ServicesController < ApplicationController
 def new
   @available_ips = Ip.where(:service_id == nil)
 end

И такой вид:

<%= 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 %>

Как сделать так, чтобы каждый выбранный IP-адрес обновлялся только что созданным service_id?

Заранее спасибо за помощь.

1 ответ

Решение

На самом деле это не вложенные атрибуты, и вам не нужны виртуальные атрибуты. Вы просто редактируете отношения "есть много".

Во-первых, вы, вероятно, хотите использовать действия edit/update для RESTful. Прочитайте руководство по маршрутизации.

В ваших маршрутах.rb:

resources :services

Затем:

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

Вам не нужен аксессор в вашей модели, коллекция является аксессором:

class Service < ActiveRecord::Base
  has_many :ips
end

class Ip < ActiveRecord::Base
  belongs_to :service
end

Тогда в ваших 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 %>
Другие вопросы по тегам