2

I have two models Hotel and Address. Relationships are:

class Hotel
  belongs_to :user
  has_one    :address
  accepts_nested_attributes_for :address

and

class Address
  belongs_to :hotel

And I need to save in hotels table and in addresses table from one form.

The input form is simple:

<%= form_for(@hotel) do |f| %>

  <%= f.text_field :title %>
  ......other hotel fields......

  <%= f.fields_for :address do |o| %>
    <%= o.text_field :country %>
    ......other address fields......

  <% end %>
<% end %>

Hotels controller:

class HotelsController < ApplicationController
  def new
    @hotel = Hotel.new
  end

  def create
    @hotel = current_user.hotels.build(hotel_params)
    address = @hotel.address.build
    if @hotel.save      
      flash[:success] = "Hotel created!"
      redirect_to @hotel
    else
      render 'new'      
    end    
  end

But this code doesn't work.

ADD 1 Hotel_params:

  private
    def hotel_params
      params.require(:hotel).permit(:title, :stars, :room, :price)
    end

ADD 2

The main problem is I don't know how to render form properly. This ^^^ form doesn't even include adress fields (country, city etc.). But if in the line

<%= f.fields_for :address do |o| %> 

I change :address to :hotel, I get address fields in the form, but of course nothing saves in :address table in this case. I don't understand the principle of saving in 2 tables from 1 form, I'm VERY sorry, I'm new to Rails...

8
  • 1
    Can you provide your hotel_params method as well, please. Commented Jul 14, 2014 at 22:17
  • Can you provide more information about what is the output of submitting this form? Commented Jul 15, 2014 at 1:12
  • @Vapire, of course, added hotel_params. Commented Jul 15, 2014 at 6:49
  • @khaled_gomaa, of course, I decribed this form in ADD2. Commented Jul 15, 2014 at 6:59
  • Your current way of having that form is correct.Don't mess with it.I guess the culprits here is your new and create methods.Can you just try my answer and say it works or not. Commented Jul 15, 2014 at 7:02

3 Answers 3

6

You are using wrong method for appending your child with the parent.And also it is has_one relation,so you should use build_model not model.build.Your new and create methods should be like this

class HotelsController < ApplicationController
  def new
    @hotel = Hotel.new
    @hotel.build_address #here
  end

  def create
    @hotel = current_user.hotels.build(hotel_params)

    if @hotel.save      
      flash[:success] = "Hotel created!"
      redirect_to @hotel
    else
      render 'new'      
    end    
  end

Update

Your hotel_params method should look like this

def hotel_params
   params.require(:hotel).permit(:title, :stars, :room, :price,address_attributes: [:country,:state,:city,:street])
end
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for your attention! With the line address = @hotel.address.build in "def new" I get an error at this line: undefined method `build' for nil:NilClass when try to access add page..
Still undefined method `build' for nil:NilClass.
@AlMacks I have updated my answer.Now it should work.
What about the foreign key? How would I set addressess :hotel_id = hotels :id?
2

You should not build address again

class HotelsController < ApplicationController
  def new
    @hotel = Hotel.new
  end

  def create
    @hotel = current_user.hotels.build(hotel_params)
    # address = @hotel.address.build 
    # the previous line should not be used
    if @hotel.save      
      flash[:success] = "Hotel created!"
      redirect_to @hotel
    else
      render 'new'      
    end    
  end

1 Comment

Thanks, khaled_gomaa!
2

Bottom line here is you need to use the f.fields_for method correctly.

--

Controller

There are several things you need to do to get the method to work. Firstly, you need to build the associated object, then you need to be able to pass the data in the right way to your model:

#app/models/hotel.rb
Class Hotel < ActiveRecord::Base
   has_one :address
   accepts_nested_attributes_for :address
end

#app/controllers/hotels_controller.rb
Class HotelsController < ApplicationController
    def new
       @hotel = Hotel.new
       @hotel.build_address #-> build_singular for singular assoc. plural.build for plural
    end

    def create
        @hotel = Hotel.new(hotel_params)
        @hotel.save
    end

    private

    def hotel_params
        params.require(:hotel).permit(:title, :stars, :room, :price, address_attributes: [:each, :address, :attribute])
    end
end

This should work for you.

--

Form

Some tips for your form - if you're loading the form & not seeing the f.fields_for block showing, it basically means you've not set your ActiveRecord Model correctly (in the new action)

What I've written above (which is very similar to that written by Pavan) should get it working for you

3 Comments

@Richard i'm not able to see the f.fields_for can you help me with this?
Are you using <%= f.fields_for ...?
What do I do about foreign keys?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.