我有以下三种模式:
class Site < AR::Base
has_many :installed_templates, :as => :installed_templateable, :dependent => :destroy
accepts_nested_attributes_for :installed_templates, :allow_destroy => true, :update_only => true, :reject_if => lambda { |t| t[:template_id].nil? }
end
class Template < AR::Base
has_many :installed_templates, :inverse_of => :template
end
class InstalledTemplate < AR::Base
belongs_to :template, :inverse_of => :installed_template
belongs_to :installed_templateable, :polymorphic => true
end
业务逻辑是,当我创建Templates
时,存在多个Site
,并且我可以通过为每个InstalledTemplate
创建Site
来尽可能多地关联。 Templates
只能有唯一的Template
- 我无法将同一Site
两次关联到一个Site
。
我在<% Template.all.each_with_index do |template| %>
<%= hidden_field_tag "site[installed_templates_attributes][][id]", Hash[@site.installed_templates.map { |i| [i.template_id, i.id] }][template.id] %>
<%= check_box_tag "site[installed_templates_attributes][]]template_id]", template.id, (@site.installed_templates.map(&:template_id).include?(template.id) %>
<%= label_tag "template_#{template.id}", template.name %>
<% end %>
的表单上有以下内容:
form_for
以上是经过大量实验后似乎唯一可行的方法。我无法使用fields_for
和{{1}}助手实现此目的。
这似乎是一种相当直接的关系,我担心我会遗漏一些东西。有人建议如何以更清洁的方式完成上述工作吗?
由于
答案 0 :(得分:3)
尝试以下
<% form_for @site do |f| %>
<%f.fields_for :installed_templates do |af|%>
<%= af.text_field :name %>
<%end%>
<%end%>
答案 1 :(得分:1)
这里是否需要连接模型?
class Site < ActiveRecord::Base
has_and_belongs_to_many :templates
end
在表单中,最简单的方法是使用simple_form:
<%= form.input :template_ids, :as => :radio_buttons, :collection => Template.order(:name), :label => 'Templates installed:' %>
如果需要连接模型,那么我会有一个下拉列表或我可以添加的模板列表,每个模板都有一个提交表单并添加该模板的按钮。然后我将使用update_only嵌套属性表单来显示当前安装的模板及其设置。
class Site < ActiveRecord::Base
...
attr_accessor :install_template_id
before_validation :check_for_newly_installed_template
def check_for_newly_installed_template
if install_template_id.present?
template = Template.find install_template_id
if template.present? and not templates.include?(template)
self.templates << template
end
end
end
end
有点像Drupal,您必须先启用主题,然后才能编辑其设置或将其选为当前主题。
答案 2 :(得分:1)
我认为你在这里尝试做两件不同的事情。
我想我会通过模型上的访问器来处理这个问题。
在站点模型上(假设标准的磁道命名约定)
attr_accessor :template_ids
def template_ids
installed_templates.collect{|i_t| i_t.template.id}
end
def template_ids=(ids, *args)
ids.each{|i| i.installed_template.build(:site_id => self.id, :template_id => i) }
end
然后表单变得非常简单
<% form_for @site do |f| %>
<% f.collection_select :template_ids, Template.all, :id, :name, {}, :multiple => true %>
<% end %>