Rails 3.1 collection_选择两个级别?(嵌套模型)



很抱歉问了一个初学者的问题。我无法获得"collection_select"在特定情况下工作。

我正在尝试基于以下模型编写一个简单的Rails3.1应用程序:

class Site < ActiveRecord::Base
     has_many :supply_sites, :dependent => :destroy
     has_many :demand_sites, :dependent => :destroy
     accepts_nested_attributes_for :supply_sites
     accepts_nested_attributes_for :demand_sites
end

class DemandSite < ActiveRecord::Base
   belongs_to :site, :class_name => "Site"
   has_many :translinks , :dependent => :destroy
end

class SupplySite < ActiveRecord::Base
   belongs_to :site, :class_name => "Site"
   has_many :translinks , :dependent => :destroy
end

class Translink < ActiveRecord::Base
  belongs_to :supply_site, :class_name =>  "SupplySite"
  belongs_to :demand_site, :class_name =>  "DemandSite"
end

迁移如下:

class CreateSites < ActiveRecord::Migration
  def self.up
    create_table :sites do |t|
      t.string :name
      t.string :codename, :limit => 3
      t.timestamps
    end
  end
  def self.down
    drop_table :sites
  end
end

class CreateSupplySites < ActiveRecord::Migration
  def self.up
    create_table :supply_sites do |t|
      t.integer :site_id
      t.float :supply_quantity
      t.timestamps
    end
  end
  def self.down
    drop_table :supply_sites
  end
end

class CreateDemandSites < ActiveRecord::Migration
  def self.up
    create_table :demand_sites do |t|
      t.integer :site_id
      t.float :demand_quantity
      t.timestamps
    end
  end
  def self.down
    drop_table :demand_sites
  end
end

class CreateTranslinks < ActiveRecord::Migration
  def self.up
    create_table :translinks do |t|
      t.integer :supply_site_id
      t.integer :demand_site_id
      t.float :unit_cost
      t.float :quantity
      t.timestamps
    end
  end
  def self.down
    drop_table :translinks
  end
end

我希望能够在从下拉菜单中选择"供应站点"one_answers"需求站点"各个供应站点或需求站点的代码名称,其中代码名称被指定为"站点"。

当添加新的"供应站点"(或"需求站点")时,以下操作效果良好(来自"_form.html.erb",适用于供应站点或需求站点。

<div class="field">
    <%= f.label :site_id %><br />
    <%= f.collection_select :site_id, Site.find(:all), :id, :codename %>
  </div>

现在我想要一些类似的东西来添加一个新的"Translink"连接供应站点和需求站点。我不想添加相应的supply_site_id或demand_site_id手动,但要根据基础站点中定义的代号选择一个需求站点。我可以做以下操作以获得下拉菜单来选择,比如说,从现有的供应站点中选择一个:

<div class="field">
    <%= f.label :supply_site_id %><br />
    <%= f.collection_select :supply_site_id,  SupplySite.find(:all), :id, :id  %>
</div>

然而,与其在下拉菜单中显示供应站点的id,我更愿意查看底层"站点"的代号并从中进行选择。

<div class="field">
    <%= f.label :supply_site_id %><br />
    <%= f.collection_select :supply_site_id,  SupplySite.find(:all), :id ,????? %>
  </div>

我该怎么做?

如有任何帮助,我们将不胜感激!

Stefan

检查formbuilder api中的fields_for方法。它允许你做一些类似的事情来处理嵌套属性:

<%= f.fields_for(options) do |nested_f|
  nested_f.text_field :nested_attribute

谢谢Katen!

解决方案是向需求站点类和供应站点类添加一个方法,如下所示:

class SupplySite < ActiveRecord::Base
  belongs_to :site, :class_name => "Site"
  has_many :translinks , :dependent => :destroy
  accepts_nested_attributes_for :translinks

 def supply_site_codename
   self.site.codename
 end

结束

class DemandSite < ActiveRecord::Base
    belongs_to :site, :class_name => "Site"
    has_many :translinks , :dependent => :destroy
    accepts_nested_attributes_for :translinks

  def demand_site_codename
     self.site.codename
  end
 end

通过这种方式,我可以使用标准的"collection_select",并引用下面的"站点"的代码名:

<div class="field">
   <%= f.label :supply_site_id %>
   <br/>
   <%= f.collection_select :supply_site_id, SupplySite.find(:all), :id,  supply_site_codename %>
 </div>
 <div class="field">
   <%= f.label :demand_site_id %>
   <br/>
    <%= f.collection_select :demand_site_id, DemandSite.find(:all), :id, :demand_site_codename %>
 </div>

现在它按要求工作。关键是要定义一种方法来引用相应的站点模型。

Stefan

最新更新