在嵌套属性上保存成功有很多通过但不添加到数据库

时间:2015-01-21 08:23:08

标签: ruby-on-rails ruby-on-rails-4 nested-attributes has-many-through

我和Rails 4的订单和项目系统有很多通过关联。当我选择创建订单时,网页显示订单已成功创建,但是未在OrderItems链接表中创建链接,这意味着与该订单相关的项目不会显示在订单的显示页面或编辑页面上。

订单也与员工相关联。当前员工ID与该订单相关联。我还没弄清楚如何将每个项目添加到数据库中。

P.S。我使用一个名为nested_form的gem来处理前端的所有jQuery,动态添加和删除_form.html.erb上的订单的新项目。

orders_controller.rb

class OrdersController < ApplicationController
  before_action :logged_in_employee, only:[:new, :show, :create, :edit, :update, :index]
  before_action :admin_employee, only:[:destroy]
  before_action :set_order, only: [:show, :edit, :update, :destroy]

  def new
    @order = Order.new
    @items = Item.all
  end

  def edit
    @items = Item.all
  end

  def create
    @order = current_employee.orders.build(order_params)
    if @order.save
      flash[:success] = "Order successfully created"
      redirect_to @order
    else
      render 'new'
    end
  end

  def update
    if @order.update_attributes(order_params)
      flash[:success] = "Order updated!"
      redirect_to current_employee
    else
      render 'edit'
    end
  end

  ....

  private

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

    def order_params
      params.require(:order).permit(:table_number, :number_of_customers, :status, :comment, order_items_attributes: [:id, :order_id, :item_id, :_destroy])
    end

end

order.rb

class Order < ActiveRecord::Base

  belongs_to :employee
  has_many :order_items
  has_many :items, :through => :order_items

  default_scope { order('status DESC') }

  validates :employee_id, presence: true
  validates :table_number, numericality: { only_integer: true, greater_than: 0, less_than_or_equal_to: 20 }, presence: true
  validates :number_of_customers, numericality: { only_integer: true, greater_than: 0, less_than_or_equal_to: 50 }, presence: true
  validates :status, inclusion: { in: %w(Waiting Ready Closed), message: "%{value} is not a status" }

  accepts_nested_attributes_for :order_items, :reject_if => lambda { |a| a[:item_id].blank? }

end

item.rb的

class Item < ActiveRecord::Base
  belongs_to :menu
  has_many :order_items
  has_many :orders, :through => :order_items

  before_save { name.capitalize! }
  VALID_PRICE_REGEX = /\A\d+(?:\.\d{0,2})?\z/

  validates :name, presence: true, length: { maximum: 100 }
  validates :price, format: { with: VALID_PRICE_REGEX }, numericality: { greater_than: 0, less_than_or_equal_to: 100}, presence: true
  validates :course, inclusion: { in: %w(Starter Main Dessert Drink), message: "%{value} is not a course" }
  validates :menu_id, presence: true

end

order_item.rb

class OrderItem < ActiveRecord::Base

  belongs_to :item
  belongs_to :order

  validates :order_id, presence: true
  validates :item_id, presence: true

end

订单/ _form.html.erb

<% provide(:title, "#{header(@order)} #{@order.new_record? ? "order" : @order.id}") %>

<%= link_to "<< Back", :back, data: { confirm: back_message } %>

<h1><%= header(@order) %> <%= @order.new_record? ? "order" : @order.id %></h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">

    <%= nested_form_for @order do |f| %>

      <%= render 'shared/error_messages', object: f.object %>

      <div class="row">
        <div class="col-xs-6">
          <%= f.label :table_number %>
          <%= f.number_field :table_number, class: 'form-control' %>
        </div>
        <div class="col-xs-6">
          <%= f.label :number_of_customers %>
          <%= f.number_field :number_of_customers, class: 'form-control' %>
        </div>
      </div>

      <%= f.fields_for :order_items do |oi| %>
        <%= oi.grouped_collection_select :item_id, Menu.where(active: true).order(:name), :items, :name, :id, :name, { include_blank: 'Select Item' }, class: 'items_dropdown' %>
        <%= oi.hidden_field :item_id %>
        <%= oi.hidden_field :order_id %>
        <%= oi.link_to_remove "Remove item" %>
      <% end %>
      <p><%= f.link_to_add "Add an item", :order_items %></p>

      <br>

      <% if !@order.new_record? %>
        <%= f.label "Status" %>
        <%= f.select(:status, options_for_select([['Waiting', 'Waiting'], ['Ready', 'Ready'], ['Closed', 'Closed']], @order.status), class: 'form-control') %>
      <% end %>

      <%= f.label "Comments - how would you like your steak cooked? Or feedback" %>
      <%= f.text_area :comment, size: "20x5", class: 'form-control' %>

      <%= f.submit submit_label(@order), class: "btn btn-success col-md-6" %>
    <% end %>

    <% if !@order.new_record? && current_employee.try(:admin?) %>
      <%= link_to "Cancel", :back, data: { confirm: back_message }, class: "btn btn-warning col-md-offset-1 col-md-2" %>
      <%= link_to "Delete", @order, method: :delete, data: { confirm: "Are you sure? The employee will be deleted! "}, class: "btn btn-danger col-md-offset-1 col-md-2" %>
    <% else %>
      <%= link_to "Cancel", :back, data: { confirm: back_message }, class: "btn btn-warning col-md-offset-1 col-md-5" %>
    <% end %>

  </div>
</div>

1 个答案:

答案 0 :(得分:1)

问题:假设您的订单包含很多商品,并且您希望在创建订单时保存商品。

   order = Order.new(order_params)
   item = Item.new(name: 'item-name', product_info: 'etc etc')

   if order.save
    item.create
    order.items << item
   end

在您的情况下,您需要遵循类似的方法。只需正确获取item_params并应用上述规则。 尝试以下方法,希望有所帮助。 :)

def create
  @order = current_employee.orders.build(order_params)

  if @order.save
    item = params["order"]["order_items_attributes"]
    #please debug above one and try to get your items from params. 
    order_item = Item.create(item)
    #makes sure above item hold all item attributes then create them first
    @order.items << item 
    redirect_to @order
  end

end