1

我有以下三个模型:

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为每个创建一个来关联任意数量的。ASite只能具有唯一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使用andfields_for助手我根本无法实现这一点。

这似乎是一种非常直接的关系,我担心我错过了一些东西。有人对如何以更清洁的方式完成上述任务有任何建议吗?

谢谢

4

3 回答 3

3

尝试以下

<% form_for @site do |f| %>

  <%f.fields_for :installed_templates do |af|%>

    <%= af.text_field :name %>
  <%end%>
<%end%>
于 2013-07-19T11:34:18.457 回答
1

我认为您正在尝试在这里做两件不同的事情。

  1. 选择要为其创建已安装模板加入站点的模板列表。
  2. 从每个选定的模板创建链接到站点的已安装模板的实例。

我想我会通过模型上的访问器来处理这个问题。

在站点模型上(假设标准 rails 命名约定)

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 %>
于 2013-07-17T14:05:32.660 回答
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,您必须先启用主题,然后才能编辑其设置或选择它作为当前主题。

于 2013-06-08T04:44:23.163 回答