Rails 5: Displaying form from Joined table

时光怂恿深爱的人放手 提交于 2019-12-22 13:49:51

问题


This is my first foray into joined tables and Many-to-Many relationships and I am relatively new to Ruby/Rails as well.

This is a direct follow up to a previous question where I built out the appropriate related tables/Models. But for sake of clarify, I'll redefine the layout here...

My Models:

order.rb

class Order < ApplicationRecord
  belongs_to :user
  has_many :quantities
  has_many :meals, through: :quantities
end

meal.rb

class Meal < ApplicationRecord
  has_many :quantities
  has_many :orders, through: :quantities
end

quantity.rb

class Quantity < ApplicationRecord
  belongs_to :order
  belongs_to :meal
  accepts_nested_attributes_for :quantities
end

user.rb

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  has_many :orders
  after_create :add_order

  def add_order
    self.create_order
  end

So each user has 1 order, and they can update the quantity of each meal on their order. I need to display all of this on a 'homepage'(I have made a home controller) of which I was given this iteration as reference:

order.quantities.each do |record|
  record.meal.name # for name of associated meal
  record.quantity # for quantity of meal
end

But the issue I am having now is incorporating this joined table into the home controller so that the page can actually display the information.

In 1-to-1 relationships, I understoop how to pull the related user's info onto the page, but in this Many-to-Many relationship, the logic is getting lost on me as anytime I bring in the information on the controller, I get an undefined variable.

I don't even want to show my attempt because I think a concept of this type of relationship is lost on me. (The method chaining used in the iteration example makes sense to me looking at it, but then how to deal with that in the controller, not a clue)

If someone could please try to explain what concept is eluding me so that I can understand Many-to-Many relationships better, I feel as though it might clarify a lot of Ruby related confusion I apparently have as well.


回答1:


To display each order and the quanties for each all you need to do is just a nested iteration:

<% user.orders.each do |order| %>
  <div class="order"> 
    <p>Ordered at <%= order.created_at %></p>
    <% order.quantites.each do |q| %>
    <div class="quantity"> 
       <%= q.meal.name >: <%= q.quantity %>
    </div>
    <% end %>
  </div>
<% end %>

You also have accepts_nested_attributes on the wrong model. It should be:

class Order < ApplicationRecord
  belongs_to :user
  has_many :quantities
  has_many :meals, through: :quantities
  accepts_nested_attributes_for :quantities
end

This lets you create nested quantities when along with an order:

Order.create(quantities_attributes: [{ meal_id: 1, quantity: 2 }, { meal_id: 3, quantity: 1 }])

You would setup the nested form like so:

<%= form_with(@order) do |f| %>
  <%= fields_for :quantities do |qf| %>
  <div class="quantity">
    <div class="field">
      <%= qf.label :meal_id %>
      <%= qf.collection_select :meal_id, Meal.all, :id, :name %>
    </div>
    <div class="field">
      <%= qf.label :quantity %>
      <%= qf.number_field :quantity %>
    </div>
  </div>
  <% end %>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

And the controller:

class OrdersController < ApplicationController

  before_action :set_order, only: [:show, :edit, :update, :destroy]

  def new
    @order = Order.new
    # this seeds the form with fields for quantities
    10.times { @order.quantities.new }
  end

  def create
    # I'm assuming you have a current_user method
    @order = current_user.orders.new(order_params)
    if @order.save
      redirect_to 'somewhere'
    else
      render :new
    end
  end

  def update
    # I'm assuming you have a current_user method
    if @order.update(order_params)
      redirect_to 'somewhere'
    else
      render :new
    end
  end

  private
    def set_order
      @order = Order.find(params[:order_id])
    end

    def order_params
      params.require(:order).permit(:foo, :bar, quantities_attributes: [:meal_id, :quantity])
    end
end


来源:https://stackoverflow.com/questions/53023671/rails-5-displaying-form-from-joined-table

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!