No commit activity in last 3 years
No release in over 3 years
Provides an ActiveModel::FormObject module that can be included into a PORO. A Rails Generator for Form Objects is included in the Gem.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies
 Project Readme

ActiveModel::FormObjects

Build Status Coverage Status Gem Version

This Gem provides an ActiveModel::FormObject module that can be included into a PORO. Includes a Rails Generator for Form Objects.

Form Objects are used to encapsulate operations which are triggered by a form submission. They are particularly useful when multiple Models need to be updated by a single form submission. A common example would be a signup form that results in the creation of both a Company and a User.

##Install

In your Gemfile

gem 'active_model_form_objects'

And then execute:

$ bundle

Creating a FormObject with the Generator

The following example generates a UserLogin form-object (and test).

$ rails generate active_model:form_object user login

The test framework your project uses will determine the type of test created:

  • For RSpec it creates:

  • Form-object: app/form_objects/user_login.rb

  • Test: spec/form_objects/user_login_spec.rb

  • For MiniTest it creates:

  • Form-object: app/form_objects/user_login.rb

  • Test: test/form_objects/user_login_test.rb

  • For TestUnit it creates:

  • Form-object: app/form_objects/user_login.rb

  • Test: test/unit/form_objects/user_login_test.rb

User Signup Example

The following example demonstrates a user signup form-object and how this would be intergrated with a form.

  • Points of interest:
  • The use of the before_validation callback hook.
  • The use of the NestedValidator to run any existing validations defined on the User model.
  • The use of the strong_parameters method on the form object instead of defining it in the controller

user_signup.rb:

require 'active_model'

class UserSignup
  include ActiveModel::FormObject

  attr_reader :user

  validates :name, :length => { :minimum => 5 }
  validates :user, :nested => true

  before_validation :create_user

  strong_parameters :user => [:name]

  private

  def create_user
    @user = User.new(user_params)
  end

  def persist!
    user.save!
  end
end

users_controller.rb:

class UsersController < ApplicationController
  respond_to :html

  def signup
    @signup_form = UserSignup.new
  end

  def create
    @signup_form = UserSignup.new(:params => params)
    if @signup_form.save()
      @user = @signup_form.user
      respond_with @user
    else
      render "signup"
    end
  end
end

signup.html.erb:

<h1>Users#signup</h1>

<%= form_for @signup_form do |f| %>
  <%= f.text_field :name %>
  <%= f.submit "Submit" %>
<% end %>

Strong Parameters

In rails 4 the strong_parameters gem is used as a method of protecting the attributes that can be passed through in the creation of a model. The usual way of doing this is defining a method on your controller:

class UsersController < ApplicationController

  private

  def user_params
    params.require(:user).permit(:name, :email)
  end

end

With The ActiveModel::FormObject::StrongParameters module this can now be defined in your form object using the strong_parameters class method. The following is the Form Object version of the user_params method above:

  class UserRegister
    include ActiveModel::FormObject

    strong_parameters :user => [:name, :email]
  end

The default implementation assumes a params method on the FormObject which can be defined in the controller as:

  UserRegister.new(:params => params)

If you wish to change the name of the params method to something else such as my_params then the strong_parameters method can be called with :my_params as an argument:

    strong_parameters, :my_params, :user => [:name, :email]

In your controller you can now do:

  UserRegister.new(:my_params => params)

Permitted Params Validator

The strong_parameters class method will record any unpermitted parameters that are included in the params object. These are stored in a unpermitted_attrs hash attribute on the FormObject. If you wish to invalidate a FormObject based on the existence of unpermitted_attrs then you can use the FormObject::Validators::PermittedParamsValidator as demonstrated in the following example:

  class UserRegister
    include ActiveModel::FormObject

    validates :user, :permitted_params => true

    strong_parameters :user => [:name, :email]
  end

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

License

This project rocks and uses MIT-LICENSE.