Using strong attributes with rails 4 and has_one relationship

1

I have a has_one relationship similar to yours where a :person has a :address .

It turns out that the relationship is generated but the street that I put in input :street (address attribute) is not saved. I already put it according to your model above and it returns error ADDRESS IS NOT DEFINED .

If you can help me, I'll be grateful.

The lab is in github: link

address.rb
class Address < ActiveRecord::Base
    belongs_to :person
end

person.rb
class Person < ActiveRecord::Base
    has_one :address
    accepts_nested_attributes_for :address
end

people_controller.rb
class PeopleController < ApplicationController
    before_action :set_person, only: [:show, :edit, :update, :destroy]

    def address
        @address
    end

    def addresses_atributes=(attributes)

    end

    # GET /people
    # GET /people.json
    def index
        @people = Person.all
    end

    # GET /people/1
    # GET /people/1.json
    def show
    end

    # GET /people/new
    def new
        @person = Person.new
        @person.build_address
    end

    # GET /people/1/edit
    def edit
    end

    # POST /people
    # POST /people.json
    def create
        @person = Person.new(person_params)
        @person.build_address
        respond_to do |format|
            if @person.save
                format.html { redirect_to @person, notice: 'Person was successfully created.' }
                format.json { render :show, status: :created, location: @person }
            else
                format.html { render :new }
                format.json { render json: @person.errors, status: :unprocessable_entity }
            end
        end
    end

    # PATCH/PUT /people/1
    # PATCH/PUT /people/1.json
    def update
        respond_to do |format|
            if @person.update(person_params)
                format.html { redirect_to @person, notice: 'Person was successfully updated.' }
                format.json { render :show, status: :ok, location: @person }
            else
                format.html { render :edit }
                format.json { render json: @person.errors, status: :unprocessable_entity }
            end
        end
    end

    # DELETE /people/1
    # DELETE /people/1.json
    def destroy
        @person.destroy
        respond_to do |format|
            format.html { redirect_to people_url, notice: 'Person was successfully destroyed.' }
            format.json { head :no_content }
        end
    end

    private
    # Use callbacks to share common setup or constraints between actions.
    def set_person
        @person = Person.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    private
    def person_params
        params.require(:person).permit(:name, :cpf, addresses_atributes: [:street, :zip_code])
    end

end

#/people/_form.html.erb
<##%= form_for(@person) do |person_form| %>




  <div class="field">
    <%#= person_form.label :name %><br>
    <%#= person_form.text_field :name %>
  </div>
  <div class="field">
    <%#= person_form.label :cpf %><br>
    <%#= person_form.text_field :cpf %>
  </div>
  <%#= person_form.fields_for :address do |address_form| %>
  <div class="field">
      <%#= address_form.label :street %>
      <%#= address_form.text_field :street %>
  </div>
  <div class="field">
      <%#= address_form.label :zip_code %>
      <%#= address_form.text_field :zip_code %>
  </div>
  <% end %>
  <div class="actions">
    <%#= person_form.submit %>
  </div>
<#% end %>
    
asked by anonymous 20.01.2015 / 11:56

1 answer

1

There are two problems in your code. The first is the nested parameter name of the template address there in person_params .

people_controller.rb

def person_params
  params.require(:person).permit(:name, :cpf, address_attributes: [:street, :zip_code])
end

And the other problem is in the create method, you should remove the @person.build_address line because it is not necessary when you are already creating a record with the data submitted by the user, use build_address only in the method new .

Remember that you should also look at the log of your app to find out this type of problem, see the log when I submit the form to create a person:

tarted POST "/people" for 127.0.0.1 at 2015-01-20 11:02:06 -0200
Processing by PeopleController#create as HTML
  Parameters: {
    "utf8"=>"✓",
    "authenticity_token"=>"rcEOWTBmMgcq3tOrNUiDForZnlB6tI4MGtg9mWurSDQ=",
    "person"=>{
      "name"=>"Person",
      "cpf"=>"0000000000",
      "address_attributes" => { "street"=>"Street name"}
    },
    "commit"=>"Create Person"
   }

Here was the answer to the wrong name problem in person_params .

    
20.01.2015 / 14:09