用于多态关联的下拉过滤器nested_attribute

时间:2013-12-02 00:51:18

标签: drop-down-menu ruby-on-rails-3.2 polymorphic-associations

我正在构建一个应用程序,用户可以在其中创建公司并添加对该公司的投资。投资可以来自两个来源用户的基金或公司的投资者。资金在应用程序中很重要,因为用户可以在其中执行大量操作。 Coinvestors并不重要,但我想控制几个方面,所以我为他们创建了一个模型。为此,我创建了一个Polymorphic协会,我给了它[可怕的] Investables的名字。我正在运行Rails 3.2.15和Ruby 2.0.0。模型如下:

class Company < ActiveRecord::Base
 has_many :investments  
 accepts_nested_attributes_for :investments
end

class Investment < ActiveRecord::Base
 belongs_to :fund, :class_name => "Fund", :foreign_key => 'investable_id'
 belongs_to :company, inverse_of: :investments
 belongs_to :coinvestor, :class_name => "Coinvestor", :foreign_key => 'investable_id'
end

class Fund < ActiveRecord::Base
  has_many :investments, :as => :investable, :dependent => :destroy
end

class Coinvestor < ActiveRecord::Base
 has_many :investments, :as => :investable, :dependent => :destroy 
end

在编辑公司时,我希望能够添加投资,并且我想为每个新投资动态添加表单行。我能够在令人敬畏的165-Edit Multiple Revised之后实现这一目标。

为了使其更复杂,我还想添加一个Dropdown来选择Polymorphic Type,以便过滤下一个Dropdown以仅显示Funds或Coinvestors的名称。 为此,我主要修改了Railscast 88-Dynamic Select Menus的代码(谢谢Ryan !!)

/views/company/edit.html.erb

<%= form_for(@company) do |f| %>
...
<%= f.fields_for :investments do |builder| %>
        <%= render 'investment_fields', f: builder %>
<% end %>
<%= link_to_add_fields "Add Investment", f, :investments, 'table' %>

/views/company/_investment_fields.html.erb

<%= f.select :investable_type , [ "Fund", "Coinvestor" ], {prompt: "Investor Type"} %>
<%= f.grouped_collection_select( :investable_id, investables_to_collection, :investables, :name, :id, :name, {prompt: "Investor"} ) %>

“investable_to_collection”是我为了聚合基金和投资者模型中的对象而构建的帮手。

module CompaniesHelper
    InvestableCollection = Struct.new(:name, :investables)
    CollectionItem = Struct.new(:name, :id)
    def investables_to_collection
        a = Array.new
        a << InvestableCollection.new('Fund', Fund.all.map { |item| CollectionItem.new(item.name, item.id )})
        a << InvestableCollection.new('Coinvestor', Coinvestor.all.map { |item| CollectionItem.new(item.name, item.id )})
        a
    end
   end

我还没有添加任何JavaScript来过滤下拉列表,这将是另一个挑战。但是我有一个美丽的视图来显示我已经在数据库中获得的数据。但应该显示基金或Coinvestor名称的下拉菜单会混淆:它会显示ID == 1的Coinvestor的名称,即使投资是由基金进行的。

我想让其中一个型号拥有自定义ID,例如f1,f2,f3 ......而不是1,2,3 ...所以系统不会混用它们。但它似乎会产生其他大的兼容性问题。

你们有其他想法吗?

1 个答案:

答案 0 :(得分:0)

我不会改变id列(即我不会从自动递增的整数中更改它),但是因为您将数据库中的两个列表混合到UI中的单个列表中需要一些方法来记录UI中每个项目来自哪个表。为此,请确保使用您想要的任何ID方案,然后使用该差异化ID作为查找相关项目的方式。

此外,如果您不打算在UI中使用自动递增id列(用于链接或其他任何内容),那么您也可以删除它们并将其替换为您的自定义标识方案。例如,没有理由不能为它们分配一个随机的8位数字,确保该数字在您要放入列表的不同类型中是唯一的,然后在UI中使用该ID。您遇到的真正问题似乎是如何组合ID可能重叠的列表,也许您可​​以设计一种方法来分配不重叠的ID。

分配非重叠ID的另一种可能性是,在不必提供自己的方案或检查多个表的唯一性的情况下,在UI下拉列表中使用UUID作为查找ID。

相关问题