26

7 种重构 Fat ActiveRecord 模型的模式- 这是一篇关于使用 PORO 进行不同重构方法的精彩文章。在第三个标题下有一个表单对象模式,我非常喜欢它,并且已经在其中一个项目中实现了它。只有一个使用一个嵌套资源的示例,但我想为多个嵌套资源实现此模式。也许这里有人已经处理过这个问题?我不一定需要任何代码示例,只要基本的想法就可以了。

更新

考虑这个例子。我有两个模型。

class Company
  has_many :users

  accepts_nested_attributes_for :users
end

class User
  belongs_to :company
end

如果公司的一个嵌套用户使用表单对象模式,我将编写以下内容:

<%= form_for @company_form do |f| %>
  <%= f.text_field :name %>
  <%= f.text_field :user_name %>
  <%= f.submit %>
<% end %>     

表单对象

class CompanyForm
  include Virtus

  extend ActiveModel::Naming
  include ActiveModel::Conversion
  include ActiveModel::Validations

  attr_accessor :company, :user

  def user
    @user ||= company.users.build
  end

  def company
    @company ||= Company.new
  end

  def submit(params={})
    company.name = params[:name]
    user.name = params[:user_name]
    persist!
  end

  private

  def persist!
    company.save!
    user.save!
  end
end 

但是如果我有一个表单,可以创建一个拥有多个用户的公司。通常的方法是这样写,使用nested_form

<%= nested_form_for @company do |f| %>
  <%= f.text_field :name %>
  <%= fields_for :users, do |user_form| %>
    <%= user.form.text_field :name %>
  <% end %>
  <%= f.link_to_add "Add a user", :users %>
  <%= f.submit %>
<% end %>

我要问的是在这种情况下如何实现该表单对象模式?

4

1 回答 1

18

rails fields_for助手检查这种格式的方法:#{association_name}_attributes=

因此,如果您将此方法添加到 CompanyForm:

def users_attributes=(users_attributes)
  # manipulate attributes as desired...
  @company.users_attributes= users_attributes
end

def users
  company.users
end

生成fields_for器将为 CompanyForm 生成嵌套的用户字段,就好像它是公司一样。上面可以重写为一个委托,因为方法中没有发生任何事情:

  delegate :users, :users_attributes=, :to => :company, :prefix => false, :allow_nil => false
于 2013-11-19T11:21:50.047 回答