DmitryTsepelev / store_model

Work with JSON-backed attributes as ActiveRecord-ish models
MIT License
1.08k stars 86 forks source link

Nested Attributes Array #74

Closed kaelumania closed 3 years ago

kaelumania commented 3 years ago

Hello,

I am trying to create a form where my models can be created in a nested fashion as well as multiple at once.

Here is my code:

class Order < ApplicationRecord
  attribute :treatment, Treatment.to_type, default: Treatment.default
end
class Treatment
  include StoreModel::Model

  MATERIALS = %i[zirkon ceramik metal]
  COLORS = %i[A2 A1]

  enum :material, MATERIALS, default: :zirkon
  enum :color, COLORS, default: :A2

  attribute :teeth, Teeth.to_array_type, default: []

  accepts_nested_attributes_for :teeth

  # https://www.dentforme.de/service/hkp_verstehen/kuerzel_behandlungsplanung/
  def self.default
    new.tap do |treatment|
      treatment.teeth << Teeth.new(id: '18')
      treatment.teeth << Teeth.new(id: '17')
      treatment.teeth << Teeth.new(id: '16')
    end
  end
end
class Teeth
  include StoreModel::Model

  APPROACHES = %i[NONE PKM]

  attribute :id, :string
  enum :approach, APPROACHES, default: :NONE
end
= form_for @order do |f|
  - if @order.errors.any?
    #error_explanation
      %h2= "#{pluralize(@order.errors.count, "error")} prohibited this order from being saved:"
      %ul
        - @order.errors.full_messages.each do |message|
          %li= message

  .field
    = f.label :treatment
    = f.fields_for :treatment do |tf|
      .field
        = tf.label :material
        = tf.select :material, Treatment::MATERIALS.map { |w| [w.to_s.humanize, w] }
      .field
        = tf.label :color
        = tf.select :color, Treatment::COLORS.map { |w| [w.to_s.humanize, w] }
      .field
        = tf.label :teeth
        = tf.fields_for :teeth do |ttf|
          - @order.treatment.teeth.each do |teeth|
            = ttf.fields_for teeth.id, teeth do |tttf| 
              = tttf.label :approach
              = tttf.select :approach, Teeth::APPROACHES.map { |w| [w.to_s, w] }

With this setup, I get the following error:

StoreModel::Types::CastError Exception: failed casting {"18"=>{"approach"=>"NONE"}, "17"=>{"approach"=>"PKM"}, "16"=>{"approach"=>"NONE"}}, only String or Array instances are allowed

I feel that my form does feel very nice, as I have to iterate over the teeth instances. But otherwise it does not work either, as the fields for helper does not detect the array.

DmitryTsepelev commented 3 years ago

Hi @kaelumania! Sorry for the silence 😔 It would be nice to have and example app to see the whole code, but two low handing fruits first:

  1. Do you have accepts_nested_attributes_for :treatments in the Order model?
  2. Did you see this thread #13 ? Looks like you either have a more complex case here or something is missing in the config (i.e., accepts_nested_attributes_for)
DmitryTsepelev commented 3 years ago

Closing the issue for now, please let me know if you need any assistance