首页 文章

Rails多个带有关联文本字段的复选框

提问于
浏览
0

我正在尝试为每种尺寸创建一个具有多种尺寸和价格的产品表单 .

我建模的方式是has_many:通过关系 . 关联表包含一个额外的价格字段,现在它将包含product_id,size_id和price .

我不确定如何创建我的表单或Rails希望如何看待它 . 任何帮助将非常感激 .

我的产品是蛋糕:)

class Cake < ApplicationRecord
  belongs_to :cake_type

  has_many :cake_details
  has_many :sizes, through: :cake_details
end

尺寸模型

class Size < ApplicationRecord
  has_many :cake_details
  has_many :cakes, through: :cake_details
end

CakeDetail模型类CakeDetail <ApplicationRecord belongs_to:cake belongs_to:size end

我的迁移

class CreateCakeDetails < ActiveRecord::Migration[5.1]
  def change
    create_table :cake_details do |t|
      t.references :cake, foreign_key: true
      t.references :size, foreign_key: true
      t.decimal :price, :precision => 10, :scale => 2
      t.timestamps
    end
  end
end

我唯一坚持的是将表格与模型联系起来 . 即对于每种尺寸,我想要一个与之相关的价格的文本框 .

目前我正在接近它,但我不知道rails如何期望文本框的id看起来或我应该如何构建它 .

这是我正在尝试的形式

<%= collection_check_boxes(:cake, :size_ids, Size.all, :id, :name) do |b| %>
    <tr>
      <td>
        <%= b.label %>
      </td>
      <td>
        <%= b.check_box %>
      </td>
      <td>
        <%= form.text_field :cake_detail, id: b.label %>
      </td>
    </tr>
<% end %>

1 回答

  • 0

    您定义业务逻辑的方式是正常的

    - A product has multiple sizes
    - Each size has a price
    

    我唯一相信它会引导你解决问题的是你正试图 create everything at the same time . 甚至Rails也可以解决你的问题,但让我们再想一想 .
    通常, Size 记录是固定的并且是事先创建的 . 这样您就不必在创建 Product 的同时创建它 .
    一旦你处理了这个想法,你的问题就变得容易了:

    • 你有一个 Size 的列表:M,L,XL,XXL ......这是事先创建的
      (您可以通过 db/seeds.rb 创建它们)

    • 你想沿着 ProductDetail 创建 Product 价格,
      并将 ProductDetail 链接到 Size

    现在你可以使用Rails的 nested_attributes 作为关系 Product -> ProductDetail

    你的模特

    # app/models/cake.rb
    class Cake < ApplicationRecord
      belongs_to :cake_type
    
      has_many :cake_details
      has_many :sizes, through: :cake_details
    
      attr_accessor :is_enable
      accepts_nested_attributes_for :cake_details, reject_if: :is_not_good_detail?
    
      private
      def is_not_good_detail?(attributed)
        return true if attributed[:is_enable].to_i != 1
        # Check if CakeDetail is good or not
      end
    end
    

    你的控制器

    # app/controllers/cakes_controller.rb
    class CakesController < ApplicationController
      def new
        @cake = Cake.new
        # Build `cake_details`, so that you can render them at view
        Size.each do |size|
          @cake.cake_details.build(size_id: size.id, price: 0)
        end
      end
    
      def create
        # Create your Cake + CakeDetail
      end
    
      private
    
      def cake_params
        # permit your params here
      end
    end
    

    你的看法

    # app/views/cakes/_form.html.erb
    <%= form_for @cake do |f| %>
      <%= f.fields_for :cakes_detail do |field| %>
        <%= field.check_box :is_enable %>
        <%= field.hidden_field :size_id %>
        <%= field.text_field :price %>
      <% end>
    <% end %>
    

    我的代码完全没有经过测试,你仍然有很多事情要做,但它应该是解决问题的正确方法 .
    您可以考虑清单来完成它:

    • 显示尺寸名称 . 例如:XL,XXL

    • 允许正确的参数

    • 拒绝无效的CakeDetail属性集 .

    • 更新时避免重复产品的大小

    <<更新>>>

    由于 check_box 仅产生 01 值,因此将其用于 size_id 是不正确的 . 我们可以通过以下方式解决

    • CakeDetail 添加 attr_accessor (例如: is_enable )并将其用于 check_box

    • size_id 成为一个隐藏的领域

    • 如果 is_enable != 1 拒绝属性

    你可以在这里找到一个工作实例yeuem1vannam/product-size

相关问题