Postgresql JSONB 嵌套形式 ruby​​ on Rails

发布于 2025-01-10 12:22:56 字数 996 浏览 1 评论 0原文

我将产品作为活动记录表,将 option_type 作为活动模型模型。选项类型是一个对象数组,如下所示,

[
  {name: 'color', values: ['red', 'blue']},
  {name: 'size', values: ['small', 'medium']}
]


class OptionType
  include ActiveModel::Model

  attr_accessor :name, :values, :default_value

  def initialize(**attrs)
    attrs.each do |attr, value|
      send("#{attr}=", value)
    end
  end

  def attributes
    [:name, :values, :default_value].inject({}) do |hash, attr|
      hash[attr] = send(attr)
      hash
    end
  end

  class ArraySerializer
    class << self
      def load(arr)
        arr.map do |item|
          OptionType.new(item)
        end
      end

      def dump(arr)
        arr.map(&:attributes)
      end
    end
  end
end

我想为 option_types 设计一个带有嵌套形式的 form_for ,以便用户可以添加各种选项名称及其值。怎么做呢?

参考链接如下,

验证数组内的对象jsonb 对象与 RubyOnRails

I have product as active record table and option_type as activemodel model. option types is an array of objects as follows,

[
  {name: 'color', values: ['red', 'blue']},
  {name: 'size', values: ['small', 'medium']}
]


class OptionType
  include ActiveModel::Model

  attr_accessor :name, :values, :default_value

  def initialize(**attrs)
    attrs.each do |attr, value|
      send("#{attr}=", value)
    end
  end

  def attributes
    [:name, :values, :default_value].inject({}) do |hash, attr|
      hash[attr] = send(attr)
      hash
    end
  end

  class ArraySerializer
    class << self
      def load(arr)
        arr.map do |item|
          OptionType.new(item)
        end
      end

      def dump(arr)
        arr.map(&:attributes)
      end
    end
  end
end

I want to desing a form_for with nested form for option_types so that user can add various option names and it's values. How to do it?

reference links are as follow,

Validation of objects inside array of jsonb objects with RubyOnRails

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

无法回应 2025-01-17 12:22:56

我知道这不是您所希望的答案,但您不应将所有内容都扔到 JSONB 列中并希望得到最好的结果,您应该尽可能以关系方式对其进行建模:

class Product < ApplicationRecord
  has_many :options
  has_many :product_options, through: :options
end

# rails g model option name:string product:belongs_to
class Option < ApplicationRecord
  belongs_to :product
  has_many :product_options
end

# rails g model product_option option:belongs_to name:string ean:string
class ProductOption < ApplicationRecord
   belongs_to :option 
   has_one :product, through: :options
end

如果您的数据实际上结构足够好如果您可以编写引用其属性的代码,那么 JSON 列不是正确的答案。 JSON/数组也不是设置关联的正确答案。

这使您可以使用外键来维护引用完整性,并具有某种程度合理的模式和查询,而不是仅仅处理完全无结构的混乱。如果您必须处理可能具有不同类型的属性,例如可以是字符串、布尔值或数字的选项,您可以使用 JSON 列来存储值,以在一定程度上减轻旧 EAV 模式的缺点。

然后,可以根据您的要求通过单独的表单、嵌套属性或 AJAX 来创建产品的变体。

I know this isn't the answer you're hoping for but instead of just tossing the whole lot into a JSONB column and hoping for the best you should model it as far as possible in a relational way:

class Product < ApplicationRecord
  has_many :options
  has_many :product_options, through: :options
end

# rails g model option name:string product:belongs_to
class Option < ApplicationRecord
  belongs_to :product
  has_many :product_options
end

# rails g model product_option option:belongs_to name:string ean:string
class ProductOption < ApplicationRecord
   belongs_to :option 
   has_one :product, through: :options
end

If your data is actually structured enough that you can write code that references its attributes then a JSON column isn't the right answer. JSON/arrays aren't the right answer for setting up assocations either.

This lets you use foreign keys to maintain referential integrity and has a somewhat sane schema and queries instead of just dealing with a totally unstructed mess. If you then have to deal with an attribute that can have varying types like for example an option that can be string, boolean or numerical you can use a JSON column to store the values to somewhat mitigate the disadvantages of the old EAV pattern.

Creating variants of a product could then either be done via a seperate form, nested attributes or AJAX depending on your requirements.

∞梦里开花 2025-01-17 12:22:56

我最近遇到了类似的问题。所以我为这个确切的问题创建了一个简单的 gem。

https://github.com/Pralish/acts_as_has_many

class Product < ActiveRecord::Base
  acts_as_has_many :option_types
  acts_as_accepts_nested_attributes_for :option_types
end
f.fields_for :option_types, @product.option_types |ff|
  ff.text_field :name
  ff.select :values, multiple: true

I came across a similar issue recently. So I created a simple gem for this exact problem.

https://github.com/Pralish/acts_as_has_many

class Product < ActiveRecord::Base
  acts_as_has_many :option_types
  acts_as_accepts_nested_attributes_for :option_types
end
f.fields_for :option_types, @product.option_types |ff|
  ff.text_field :name
  ff.select :values, multiple: true
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文