【问题标题】:Rails - has_many :through association + save data for associationRails - has_many:通过关联+保存关联数据
【发布时间】:2016-08-24 07:21:24
【问题描述】:

我已经设置了 has_many 和 has_many :通过 Order、User、Product 和 Order_detail 模型之间的关联作为连接表。

型号:

class Order < ActiveRecord::Base
  has_many :order_details
  belongs_to :user
  has_many :products, through: :order_details
end

class OrderDetail < ActiveRecord::Base
  belongs_to :order
  belongs_to :product
end

class Product < ActiveRecord::Base
  has_many :order_details
  has_many :orders, through: :order_details
end

class User < ActiveRecord::Base
  has_many :orders
end

如何为连接表 order_details 自动保存。 现在数据只保存到订单表。 需要将所有产品保存到 order_tables 以供当前订单和用户使用

class OrdersController < ApplicationController
  before_action :authenticate_user!

  def index
    @order = Order.all
  end

  def new
    # @order = Order.new
    @order = current_user.orders.new
  end

  def create
    @order = current_user.orders.new(order_params)
    @order.date = Date.today.to_s
    if @order.save
       # i think this is bad wrong to implementation of functional)
       # params[:product_id].each do |detail_product_id|
       # @order.order_details.product_id = detail_product_id
       # @order.order_details.user_id = current_user
       # @order.order_details.save
       flash[:success] = "Order was successfully submitted"
       redirect_to new_order_path
    else
      render :new
    end
  end

 private

 def order_params
   params.require(:order).permit(:date, :product_id => [])
 end
end

我的架构:

create_table "order_details", force: true do |t|
  t.integer  "order_id"
  t.integer  "product_id"
  t.integer  "quantity"
  t.integer  "price"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
end

create_table "orders", force: true do |t|
 t.integer "user_id"
 t.date    "date"
end

add_index "orders", ["user_id"], name: "index_orders_on_user_id", using: :btree

create_table "orders_products", id: false, force: true do |t|
  t.integer "order_id"
  t.integer "product_id"
end

create_table "products", force: true do |t|
  t.string   "product_name"
  t.integer  "product_price"
  t.datetime "created_at",       null: false
  t.datetime "updated_at",       null: false
  t.boolean  "available_status"
  t.string   "product_type"
end

【问题讨论】:

标签: ruby-on-rails ruby-on-rails-4 associations has-many-through has-many


【解决方案1】:

在您看来,为 order_details 添加字段,例如:

     <%= f.fields_for :order_details do |od| %>
       <%= od.label 'your attribute for OrderDetail' %>
       <%=  # od.text_field 'your attribute' %>
     <% end %>

然后在您的模型中,接受 order_details 的嵌套属性 喜欢:

    accepts_nested_attributes_for :order_details

这些是示例值,您可以将此逻辑与您的实际属性一起使用。

在您的控制器中,允许 order_details 的属性,例如:

    params.require(:order).permit(:id, :name, order_details: [
      #attributes of order details
    ])

【讨论】:

    【解决方案2】:

    假设 product_ids 是您希望添加到订单中的产品 ID 数组,您可以尝试按以下方式分配它们,然后当您调用 @order.save

    @order.products << Product.find_by_id(product_ids)
    

    【讨论】:

      【解决方案3】:

      我是否正确地为控制器添加了这些行? Order_controller:

        def create
          @order = current_user.orders.new(order_params)
          @order.products = Product.find_by_id(order_params[:product_ids])
          @order.date = Date.today.to_s
          if @order.save
            flash[:success] = "Order was successfully submitted"
            redirect_to new_order_path
          else
            render :new
          end
        end
      
       private
       def order_params
         params.require(:order).permit(:date, order_details: [:product_id])
       end
      end
      

      订购型号:

        accepts_nested_attributes_for :order_details
      

      我正在尝试保存 3 种不同类型的产品。

      • 但是如何从每个零件中获取一个产品 ID 呢?因为现在我只能从所有产品中选择一种

      查看:

      = simple_form_for(@order, html: {:class => 'well form-horizontal', :method  => :post, :action=> :create }) do |f|
          .col-xs-12.col-sm-6.col-md-8
          = render 'shared/error_messages', object: f.object
          %br
          = simple_fields_for :order_details do |od|
             = od.collection_radio_buttons :product_ids, Product.get_first_course, :id, :product_name ,:item_wrapper_class => 'inline'
            %hr
            = od.collection_radio_buttons :product_ids, Product.get_main_course, :id, :product_name, :item_wrapper_class => 'inline'
            %hr
            = od.collection_radio_buttons :product_ids, Product.get_drink, :id, :product_name,:item_wrapper_class => 'inline'
           %hr
         = f.button :submit, class: "btn btn-primary"
      

      【讨论】:

      • 我对 simple_form 的东西无能为力,但快速浏览一下控制器应该稍微改变一下。 order.products = Product.find_by_id(order_params[:product_ids]) 不起作用,因为 @order.products 是一个集合。将 = 更改为
      • 另外,在您的强大参数中,您可能需要将 .permit(:date, order_details: [:product_id]) 更改为 .permit(:date, order_details: [product_ids: []])
      • 推送和
      • 是的
      【解决方案4】:

      我将关联类型更改为 HABTM,这对于我的情况来说已经足够了。所以..

      型号:

        class Order < ActiveRecord::Base
         has_and_belongs_to_many :products
         before_destroy { products.clear }
        end
        class Product < ActiveRecord::Base
         has_and_belongs_to_many :orders
        end
      

      订单控制器:

      def create
        order = current_user.orders.new(date: Date.today.to_s)
        @order_products = Product.where(id: order_params[:product_ids])
        order.products << @order_products
        if order.save
          #blalblal - sucsess
        else
          #blabla - alert-notice
        end
      

      【讨论】:

        猜你喜欢
        • 2013-11-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-13
        • 2011-12-04
        • 1970-01-01
        • 2015-01-27
        • 2016-12-04
        相关资源
        最近更新 更多