Rails association gives one-to-many relationships between models

Introduction

After I, a Rails beginner, associated tables by association I had a lot of trouble not passing the parameters to the action method, so I will write an article. The goal is to give the Place (cafe) information about the menus and output it on the screen.

Check the Place and Menu columns for the time being

irb(main):005:0> Place.column_names
=> ["id", "name", "message", "created_at", "updated_at", "user_id"]
irb(main):006:0> Menu.column_names
=> ["id", "title", "price", "message", "created_at", "updated_at", "place_id"]

It will be as above.

The logged-in User posts his favorite cafe → Menu information can also be added to that cafe. It is a function called.

Joining tables by association

app/models/place.rb


class Place < ApplicationRecord
  belongs_to :user
  has_many :menus
end

Be careful not to confuse this singular and plural description, as naming conventions are important in Rails. It has (one) place for (one) user and (multiple) menus for (one) place.

belongs_to (belongs to) has_many (has a lot) ... It's easy to understand!

app/models/menu.rb


class Menu < ApplicationRecord
  belongs_to :place
end

menu.rb looks like this.

For the time being, the linking between the tables is complete.

places_controller.rb


    [1] pry(#<PlacesController>)> @place
=> #<Place:0x00007f9d1e88cc10
 id: 3,
 name: "hoge Coffee",
 message: "The calm atmosphere at the nearest cafe from home is very nice.",
 created_at: Thu, 18 Jun 2020 00:05:20 UTC +00:00,
 updated_at: Thu, 18 Jun 2020 13:14:42 UTC +00:00,
 user_id: 1>
[2] pry(#<PlacesController>)> params
=> <ActionController::Parameters {"controller"=>"places", "action"=>"show", "id"=>"3"} permitted: false>

I want to register the menu from views / places / show.html.erb, so check the parameters. This is the information of the cafe you want to register the menu this time.

ruby:places/show.html.erb


  <%= link_to 'Register menu', new_menu_path(id: @place.id) %>

Go to the new action of menus_controller to register the menu.

If you do not pass an argument to the _path helper at this time, you will not be able to search for place with the new action of menus_controller.

menus_controller.rb


class MenusController < ApplicationController

  def new
    @menu = Menu.new
    @place = Place.find_by(id: params[:id])
  end
(Abbreviation)

Input form ↓

ruby:menus/new.html.erb


<%= form_with model:@menu, local: true do |f| %>
<h2>Register menu</h2>
<p>The name of the dish: <%= f.text_field :title %></p>
<p>Price : <%= f.text_field :price %></p>
<%= f.hidden_field :place_id, :value => @place.id %>
<%= f.submit 'sign up' %>
<% end %>

Since place_id is not something to enter, it will receive the value passed in hidden_field.

How to receive place_id in create action, but receive it in the input form when registering the menu.

menus_controller.rb


def create
    #Receive the parameters received in the input form here
    @menu = Menu.create(
      title: menus_params[:title],
      price: menus_params[:price],
      place_id: menus_params[:place_id]
    )
    #I will check if I have received it properly here
    binding.pry
end

(Omission)

private

  def menus_params
    params.require(:menu).permit(:title, :price, :place_id)
  end

(Abbreviation)

I will fill out the form for confirmation. result···

python


[1] pry(#<MenusController>)> menus_params
=> <ActionController::Parameters {"title"=>"iced coffee", "price"=>"280", "place_id"=>"3"} permitted: true>

I was able to receive the place_id properly.

Now you can receive parameters that have a proper one-to-many relationship (menus for place).

    <% @place.menus.each do |menu| %>
        <p><%= menu.title %> <%= menu.price %></p> 
    <% end %>

The registered menu can be output like this.

[1] pry(#<PlacesController>)> @place.menus
  (Abbreviation)
=> [#<Menu:0x00007ffda376a4c8
  id: 37,
  title: "Chocolate cake",
  price: 250,
  created_at: Thu, 18 Jun 2020 01:36:00 UTC +00:00,
  updated_at: Thu, 18 Jun 2020 01:36:00 UTC +00:00,
  place_id: 3>,
 #<Menu:0x00007ffda3773eb0
  id: 44,
  title: "iced coffee",
  price: 280,
  created_at: Fri, 19 Jun 2020 00:24:50 UTC +00:00,
  updated_at: Fri, 19 Jun 2020 00:24:50 UTC +00:00,
  place_id: 3>]

Since it is linked by the association, you can check the menu registered with @ place.menus.

Recommended Posts

Rails association gives one-to-many relationships between models
Association (one-to-many)! !!
Association (one-to-many relationship)
[Rails] Model Association (Association)
Model association in Rails
Ruby On Rails Association