1

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

0

2 Answers 2

0

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.