Skip to content

nikolay-slavov/MiniForm

 
 

Repository files navigation

Gem Version Code Climate Build Status Code coverage

MiniForm

Helpers for dealing with form objects and nested forms.

Installation

Add this line to your application's Gemfile:

gem 'mini_form'

And then execute:

$ bundle

Or install it yourself as:

$ gem install mini_form

Usage

class ProductForm
  include MiniForm::Model

  attributes :id, :name, :price, :description

  validates :name, :price, :description, presence: true

  # called after successful validations in update
  def perform
    @id = ExternalService.create(attributes)
  end
end
class ProductsController < ApplicationController
  def create
    @product = ProductForm.new

    if @product.update(product_params)
      redirect_to product_path(product.id)
    else
      render :edit
    end
  end

  private

  def product_params
    params.require(:product).permit(:name, :price, :description)
  end
end

Delegated attributes

Attributes can be delegated to a sub object.

class SignUpForm
  include MiniForm::Model

  attr_reader :account, :user

  attributes :name, :email, delegate: :user
  attributes :company_name, :plan, delegate: :account

  validates :name, :email, :company_name, :plan, presence: true

  def initialize
    @account = Account.new
    @user    = User.new account: @account
  end

  def perform
    user.save!
    account.save!
  end
end
form = SignUpForm.new
form.name = 'name' # => form.user.name = 'name'
form.name          # => form.user.name
form.plan = 'free' # => form.account.plan = 'free'
form.plan          # => form.account.plan

Nested validator

mini_form/nested validator runs validations on the given model and copies errors to the form object.

class SignUpForm
  include MiniForm::Model

  attr_reader :account, :user

  attributes :name, :email, delegate: :user
  attributes :company_name, :plan, delegate: :account

  validates :account, :user, 'mini_form/nested' => true

  def initialize
    @account = Account.new
    @user    = User.new account: @account
  end

  def perform
    account.save!
    user.save!
  end
end

Nested models

Combines delegated attributes and nested validation into a single call.

class SignUpForm
  include MiniForm::Model

  model :user, attributes: %i(name email)
  model :account, attributes: %i(company_name plan)

  def initialize
    @account = Account.new
    @user    = User.new account: @account
  end

  def perform
    account.save!
    user.save!
  end
end

Auto saving nested models

In most of the time perform is just calling save!.

class SignUpForm
  include MiniForm::Model

  model :user, attributes: %i(name email), save: true
  model :account, attributes: %i(company_name plan), save: true

  def initialize
    @account = Account.new
    @user    = User.new account: @account
  end
end

Before/after callbacks

class SignUpForm
  include MiniForm::Model

  # ... code

  before_update :run_before_update
  after_update :run_after_update

  private

  def run_before_update
    # ...
  end

  def run_after_update
    # ...
  end

  # alternatively you can overwrite "before_update"
  def before_update
  end

  # alternatively you can overwrite "after_update"
  def after_update
  end
end

Methods

Method Description
.model Defines a sub object for the form
.attributes Defines an attribute, it can delegate to sub object
#initialize Meant to be overwritten. By defaults calls `attributes=`
#attributes= Sets values of all attributes
#attributes Returns all attributes of the form
#update Sets attributes, calls validations, saves models and `perform`
#update! Calls `update`. If validation fails, it raises an error
#perform Meant to be overwritten. Doesn't do anything by default
#before_update Meant to be overwritten.
#after_update Meant to be overwritten.
#transaction If ActiveRecord is available, wraps `perform` in transaction.

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. Run the tests (rake)
  6. Create new Pull Request

License

MIT License

About

Sugar around ActiveModel::Model

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Ruby 100.0%