Automatically create a has_one and belongs_to associations object

    If you ever had a wonderful situation when you registered associations for models (has_one and belongs_to), accepted_nested_attributes, but the fields_for helper does not show the form, then this post will help you get rid of this “glitch” once and for all. I warn you in advance that the post is purely for rails developers, and no one will be interested in developers except rails for anyone!


    Preconditions

    So, let's say we have the following models:

    class Company < ActiveRecord::Base
        belongs_to :location
        has_one :user
        accepts_nested_attributes_for :user
        accepts_nested_attrbiutes_for :location
    end
    class User < ActiveRecord::Base
        belongs_to :company
    end
    class Location < ActiveRecord::Base
        has_one :company
    end
    


    We need a company form with user and location resources nested. At first glance, it might seem that the code:

    form_for :company do |f|
        f.text_field :name
        f.fields_for :user, f.object.user_or_build do |fu|
            fu.text_field :name
        end
        f.fields_for :location, f.object.location_or_build do |fl|
            fl.text_field :address
        end
    end
    


    will be enough to show the desired shape. However, it is not. By launching the application and opening the browser, you will see that instead of the expected 3 fields on the page, there is only one thing - this is the name field for company (it is assumed that we have an initialized object like this:
    @company = Company.new
    )

    What is wrong with this code?


    The problem is that we did not initialize the associated user and location objects for @company:

    @company.build_location # то же что и @company.location = Location.new
    @company.build_user # то же что и @company.user = User.new
    


    If these conditions are met before the field_for helpers are executed, the form will look as we expected. However, writing such code every time in the controllers is somehow not serious, because the controllers must be clean!

    Decision

    This problem can be avoided with the help of this gem , which has a slightly awkward name - get_or_build .
    Add the line to the Gemfile:
        gem 'get_ot_build'
    


    Install gems: bundle install, restart the application and refactor the fields_for helpers as follows:

        form_for :company do |f|
            f.fields_for :user, :build_association => true do |fu|
                fu.text_field :name
            end
            f.fields_for :user, :build_association => true do |fl|
                fl.text_field :address
            end
        end
    


    After that, the initialization code for user and location association objects can be removed from controllers, templates, and helpers (somewhere else where it is;) and is no longer needed).

    I would be very grateful for the criticism and comments, volunteers for the development of the gem are also welcome. Thanks for attention!

    Also popular now: