Today I Learned

This project exists to catalogue the sharing & accumulation of knowledge as it happens day-to-day. Posts have a 200-word limit, and posting is open to any Rocketeer as well as selected friends of JetRockets. We hope you enjoy learning along with us.

1 post by Maksim Agafonov

Form_for and Rails attributes API

Attributes API allows you to have complex object with specified structure in fields. But how to make forms with this fields?

The answer is pretty simple: you work with them like with nested attributes.

Let’s say, we have class Provider with attribute address.

class Provider < ApplicationRecord
  attribute :address, Provider::Address::Type.new, default: Provider::Address.new

Address has following attributes:

class Provider::Address
  extend Dry::Initializer

  option :country, optional: true
  option :zip, optional: true
  option :city, optional: true
  option :address, optional: true

Form will look like this:

= form_for resource_provider, provider_url do |f|
  = f.fields_for :address do |ff|
      = ff.label 'Country'
      = ff.text_field :country, value: @provider.billing_address.country
      
      = ff.label 'Zip'
      = ff.text_field :zip, value: @provider.billing_address.zip
      
      = ff.label 'City'
      = ff.text_field :city, value: @provider.billing_address.city
      
      = ff.label 'Address'
      = ff.text_field :address, value: @provider.billing_address.address

In controller you have to permit parameters:

def provider_params
    params.require(:provider).permit(address: [:city, :zip, :country, :address])
end

And that’s all. Now, in action method you can assign attributes like this:

resource_provider.attributes = provider_params
resource_provider.save