【问题标题】:Rails Formtastic nested form - form for attributes from join modelRails Formtastic 嵌套表单 - 来自连接模型的属性表单
【发布时间】:2012-01-07 12:01:31
【问题描述】:

Formtastic 面临的问题是我有一个表单来创建一个新的Order。在此表单中,我想从列表中选择多个现有的 Food 项目。这些应添加到我提交的新订单中。同时我也想在FoodOrderjoin模型中设置属性。这个模型有一个整数数量属性,我想在我的表单中有一个字段。

我基本上要寻找的是一个表格,它列出了所有食品,并将quantity 的字段与它所属的食品放在同一行。

模型

class Order < ActiveRecord::Base
  belongs_to :user
  belongs_to :restaurant
  has_many :food_orders
  has_many :foods, :through => :food_orders
end

class FoodOrder < ActiveRecord::Base
  belongs_to :food
  belongs_to :order
end

class Food < ActiveRecord::Base
  has_many :food_orders
  has_many :orders, :through => :food_orders
  belongs_to :category
end

这是迄今为止我尝试过的表单版本之一。但我很困惑,不知道如何获取 FoodOrder 模型的字段。

<%= semantic_form_for [@restaurant, @order] do |f| %>
  <%= f.inputs do %>
    <%= f.input :comment %><br />
    <%= f.input :table_id %><br />
    <%# <%= f.input :foods, :as => :check_boxes %>
    <%= f.inputs :for => :foods do |food| %>
      <%= food %>
      <%= food.inputs :quantity %>
    <% end %>
  <% end %>
  <%= f.buttons do %>
    <%= f.commit_button %>
  <% end %>
<% end %>

我的模型有这些属性

create_table "food_orders", :force => true do |t|
  t.integer  "quantity",   :null => false
  t.decimal  "price",      :null => false
  t.integer  "food_id",    :null => false
  t.integer  "order_id",   :null => false
  t.text     "comment"
  t.datetime "created_at", :null => false
  t.datetime "updated_at", :null => false
end

create_table "foods", :force => true do |t|
  t.integer  "category_id",                     :null => false
  t.string   "name",                            :null => false
  t.string   "description"
  t.string   "image"
  t.decimal  "default_price",                   :null => false
  t.boolean  "active",        :default => true, :null => false
  t.datetime "created_at",                      :null => false
  t.datetime "updated_at",                      :null => false
end

create_table "orders", :force => true do |t|
  t.integer  "restaurant_id",                    :null => false
  t.integer  "user_id",                          :null => false
  t.integer  "table_id",                         :null => false
  t.decimal  "total",                            :null => false
  t.datetime "finished_at"
  t.datetime "created_at",                       :null => false
  t.datetime "updated_at",                       :null => false
end

【问题讨论】:

    标签: ruby-on-rails forms nested-forms formtastic nested-attributes


    【解决方案1】:

    基本上我最终会为每个Food 创建一个FoodOrder 对象,然后只保存值大于0 的对象。

    您可以在reject_if 中为accepts_nested_attributes_for 执行此操作,但这不会删除旧的FoodOrders,有人可能会将其从3 更改为0。因此,您将不得不覆盖quantity= 方法为FoodOrder

    我以前从未使用过formtastic,但我会猜测一下,这应该可以工作。

    <%= semantic_form_for [@restaurant, @order] do |f| %>
      <%= f.inputs do %>
        <%= f.input :comment %><br />
        <%= f.input :table_id %><br />
        <% @foods.each do |food|
          <%= f.semantic_fields_for :food_orders, 
                                @order.food_orders.detect_or_build_by_food(food)
                                do |food_order| %>
            <%= food %>
            <%= food_order.inputs :quantity %>
          <% end %>
        <% end %>
      <% end %>
      <%= f.buttons do %>
        <%= f.commit_button %>
      <% end %>
    <% end %>
    

    order.rb:

    class Order < ActiveRecord::Base
      belongs_to :user
      belongs_to :restaurant
      has_many :foods, :through => :food_orders
      has_many :food_orders do
        def detect_or_build_by_food(food)
          record = self.detect{ |food_order| food_order.food_id == food.id }
          if record.nil?
            record = self.build(:food => food)
          end
          record
        end
      end
    
      accepts_nested_attributes_for :food_orders
    end
    

    food_order.rb:

    class FoodOrder < ActiveRecord::Base
      belongs_to :food
      belongs_to :order
    
      def quantity=(quantity)
        if quantity <= 0
          self.destroy
        else
          self[:quantity] = quantity
        end
      end
    end
    

    我希望它有效,但它是未经测试的代码,所以是的......祝你好运!

    【讨论】:

    • 感谢您的回答!!表格现在看起来不错,就像我正在寻找的一样。不幸的是,我收到了 can't modify frozen hash Rails 运行时错误。 FoodOrder里面的数量是不是不能修改?知道错误可能来自哪里吗?
    • 嗯,这可能是我将要在手机上使用的方法中的破坏,但您可以尝试“mark_for_destruction”。但如果这不起作用,请完全取出破坏,看看会发生什么。
    • 感谢您的快速回复。 .mark_for_destruction 和评论都不行。两者都导致SQLite3::ConstraintException: constraint failed: INSERT INTO "food_orders"
    • 您可能需要一个带有“food_id”的隐藏字段。该错误通常意味着数据库没有获得所需的值
    • 我为food_id 添加了一个隐藏字段,但我仍然得到相同的声明无效。很奇怪。 {"utf8"=>"✓", "authenticity_token"=>"PxvWreNiO3ApTojDS5AmyusMnM1A8NNHPSsec4Pghhw=", "order"=>{"table_id"=>"1", "food_orders_attributes"=>{"0"=>{"quantity" =>"1", "comment"=>"hey", "food_id"=>"1"}, "1"=>​​{"quantity"=>"", "comment"=>"", "food_id" =>"2"} }, "commit"=>"创建订单", "restaurant_id"=>"1"}
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-12
    • 1970-01-01
    相关资源
    最近更新 更多