Reform Documentation

repository·master·Indexed 25 days ago

https://github.com/trailblazer/reform

A framework-agnostic form object library for Ruby that decouples form logic, validations, and nested setup from underlying data models. It provides a minimal API for handling input, validation, and syncing data back to models, with support for nested forms, collections, and composition. Reform supports multiple validation backends, including dry-validation and ActiveModel, and offers integration with Rails via the reform-rails gem.

Tokens
5.4K
Snippets
8
Records
36
Agent score
81%

What's inside Reform

  1. Define nested forms and collections

    master

    Reform supports nested objects and collections. When you define a property as a nested block or a collection, Reform automatically wraps the associated models in their own form objects during initialization.

    • Use property :name do ... end for has_one relationships.
    • Use collection :name do ... end for has_many relationships.
    • You can reuse existing forms using the form: FormClass option.
    class AlbumForm < Reform::Form
      property :title
      validates :title, presence: true
    
      # Nested single object
      property :artist do
        property :full_name
        validates :full_name, presence: true
      end
    
      # Nested collection
      collection :songs do
        property :name
      end
      
      # Reusing an existing form
      property :artist, form: ArtistForm
    end
  2. Compose a form from multiple models

    master

    Reform allows a single form to map to multiple models using the Composition module. When initializing a composed form, you must pass a hash containing the models (the 'composees').

    class AlbumForm < Reform::Form
      include Composition
    
      property :id,    on: :album
      property :title, on: :album
      property :songs, on: :cd
      property :cd_id, on: :cd, from: :id
    end
    
    # Initialization
    AlbumForm.new(album: album, cd: CD.find(1))
  3. Define a Reform form

    master

    Forms are defined as separate classes inheriting from Reform::Form. You declare fields using property and define validations within the class. This decouples form logic and validations from your underlying models.

    class AlbumForm < Reform::Form
      property :title
      validates :title, presence: true
    end
  4. Setup and render forms in a controller

    master

    In your controller, instantiate the form by passing in a new or existing model. The form will automatically populate its properties by calling readers on the model.

    When rendering, you can pass the Reform instance directly to Rails form helpers like form_for or simple_form. For nested forms, use fields_for or access the nested form objects via the form's readers.

    # Controller setup
    class AlbumsController
      def new
        @form = AlbumForm.new(Album.new)
      end
    
      def edit
        @form = AlbumForm.new(Album.find(1))
      end
    end
    # View rendering (Haml example)
    = form_for @form do |f|
      = f.input :title
    
    # Nested rendering with fields_for
    = form_for @form do |f|
      = f.text_field :title
      = f.fields_for :artist do |a|
        = a.text_field :name
  5. Install Reform and configure validation backends

    master

    Add reform to your Gemfile. Since Reform 2.2, if you are using Rails, you must also add the reform-rails gem to automatically load ActiveModel files.

    Starting from Reform 2.0, you must explicitly specify a validation backend. It is highly recommended to use dry-validation instead of the outdated ActiveModel validations.

    # Gemfile
    gem "reform"
    # Required for Rails integration in Reform 2.2+
    gem "reform-rails"

    Configure dry-validation (Recommended)

    Put this in an initializer or at the top of your script

    require "reform/form/dry" Reform::Form.class_eval do feature Reform::Form::Dry end

    Configure ActiveModel (Not recommended)

    require "reform/form/active_model/validations" Reform::Form.class_eval do include Reform::Form::ActiveModel::Validations end

  6. Validate and save form data

    master
    After form submission, call #validate(params) with the input hash. If it returns true, you can call #save to sync the data to the model and trigger the model's own #save method. If you need manual control over the saving process, call #save with a block. The block receives a nested hash of the form's properties.
  7. Populate if empty using a Class or Proc

    master

    Reform provides a mechanism to ensure a model is instantiated if it is currently nil. While the source code references IfEmpty (used internally for :prepopulate and similar logic), the pattern for populating an empty slot involves providing a Class or a Callable.

    If you provide a Class, Reform will instantiate it: form.songs.insert(Song.new).

    If you provide a Proc, it is evaluated with the current form and options context.

  8. Customize deserialization in Reform forms

    master

    Reform allows you to override how input parameters are transformed into data the form can use. This is typically done by overriding the deserialize! method or providing a custom deserializer.

    Overriding deserialize!

    Use deserialize! to transform the input hash (e.g., 'munching' date fields or handling specific type conversions) before it is passed to the deserializer. The method should return the transformed parameters.

    Using a custom deserializer

    By default, Reform uses a Disposable::Rescheme based deserializer. You can influence this behavior by interacting with the deserializer method or the deserializer_class attribute on the form class.

  9. Define form structures with Reform::Contract

    master

    To define a form's structure and its validations, inherit from Reform::Contract. A contract acts as a 'twin' to a model, allowing you to define properties and validation rules that apply to the object graph. You instantiate a contract with a model and then use it to validate the data.

    Key capabilities include:

    • Defining properties using property or properties.
    • Applying validations directly within the property definition using the validates option.
    • Using valid? and validates methods (via Reform::Validation) to check data integrity.
  10. Integrate Dry::Validation with Reform forms

    master

    You can use dry-validation contracts to define the validation logic for your Reform forms. By including Reform::Form::Dry in your form class, you gain access to validation groups that wrap Dry::Validation::Contract instances. This allows you to leverage the powerful schema and rule definitions of dry-validation within the Reform lifecycle.

    To use this integration, ensure you have the dry-validation gem (version ~> 1.5) in your project.

    gem 'dry-validation', '~> 1.5'
  11. Initialize the Reform library

    master
    To use Reform, require the reform library. This entrypoint loads the core components including Reform::Contract, Reform::Form, and support for form composition and modules. It also requires the disposable gem to be present in your environment.