Sunday 23 April 2017

Update attr_accessor wiithin accepts_nested_attributes_for in Rails


Suppose that we have association like this -

        class Employer < ApplicationRecord
          
          has_one :account
          accepts_nested_attributes_for :account

        end 


and
        class Account < ApplicationRecord

          belongs_to :employer
          attr_accessor :area

        end


In above association account belongs_to employer and has attr_accessor attributes :area.

Now, we have form like this -
        <%= form_for(@employer) do |f| %>
        
            <%= f.fields_for :account do |acc| %>
              <%= acc.file_field :account_number %>        
              <%= acc.file_field :area %>
            <% end %>
        <% end %>


So, we want to update account attributes within employer update method. For this we have to white-list it in employer strong parameter -

In employers controller,

    def update

        if @employer.update(employer_params)

          flash[:notice] = 'Employer updated Successfully'

          redirect_to employer_path

        else

          flash[:notice] = @employer.errors.full_messages.to_sentence

          redirect_to employer_path

        end

      end


    private

      def employer_params
        params.require(:employer).permit(:name, :email, :password, :role, account_attributes: [:id, :account_number, :area])
      end 


From above method it will update attr_accessor attributes only when we will update account_number attributes.

But what if we want only update attr_accessor attributes that is :area. It won't be updated if none of account attributes updating same time.

For updating attr_accessor wiithin accepts_nested_attributes_for we have to do couple of things -

In Account.rb
    

    class Account < ApplicationRecord

        
          belongs_to :employer
          attr_accessor :area


        def new_attr=(a)
          attribute_will_change!(:name)
          self.area = a
        end



    end


and in strong parameters of employers controller -
    def employer_params
      params.require(:employer).permit(:name, :email, :password, :role, account_attributes: [:id, :account_number, :new_attr])
    end