26

7 Patterns to Refactor Fat ActiveRecord Models - here is a great article about different refactoring approaches using PORO. Under the 3rd caption there is a Form Object pattern, which I really liked and already implemented in one of the projects. There is only an example using one nested resource, but I would like to implement this pattern for multiple nested resources. Maybe someone here had already dealt with this? I don't necessarily need any code examples, just the basic idea would be fine.

Update

Consider this example. I have two models.

class Company
  has_many :users

  accepts_nested_attributes_for :users
end

class User
  belongs_to :company
end

In case of one nested user for company using Form Object Pattern I would write the following:

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

Form Object

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 

But what if I have a form, where a company with multiple users can be created. The usual approach is to write it like this, using 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 %>

What I am asking is how do I implement that Form Object Pattern in this case?

3
  • This is not really a question, so it will be hard to answer. Can you please post some code and ask a more specific question? Thanks. Commented Jul 31, 2013 at 19:43
  • This is a great question, that I am trying to find more info on. Did you ever resolve this issue with form objects? Commented Sep 13, 2013 at 3:59
  • Haven't yet, but the first thing that comes to my mind is to make a custom link_to_add/remove helper (like one in nested_form gem) where a new instance of form object should be constructed instead of a new model. Commented Sep 13, 2013 at 10:42

1 Answer 1

19

the rails fields_for helper checks for a method in this format: #{association_name}_attributes=

so, if you add this method to CompanyForm:

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

def users
  company.users
end

the fields_for generators will generate the nested users fields for a CompanyForm as if it were a Company. the above could be rewritten as a delegation since nothing is happening in the methods:

  delegate :users, :users_attributes=, :to => :company, :prefix => false, :allow_nil => false
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.