store_model icon indicating copy to clipboard operation
store_model copied to clipboard

Nested Attributes?

Open exsemt opened this issue 5 years ago • 22 comments

Hi @DmitryTsepelev,

are you planning to add the accept_nested_attributes_for function to the store_model?

exsemt avatar Jul 12 '19 14:07 exsemt

Hi @exsemt!

Please take a look at the discussion in this issue #7, where we've discussed an ability to update store_model as a nested association. Do you want the same thing or you have one store_model inside another?

DmitryTsepelev avatar Jul 12 '19 14:07 DmitryTsepelev

Yes, I have one store_model inside another:

class Concept
  include StoreModel::Model

  attribute :id, :integer
  attribute :name, :string
  attribute :values, ConceptValue.to_array_type

  # fix for nested attributes
  def values_attributes=(values)
    self.values = values.values
  end
end

class ConceptValue
  include StoreModel::Model
  
  attribute :name, :string
  ...
end

It will be greate to have some like accept_nested_attributes_for and not to write values_attributes=

exsemt avatar Jul 12 '19 15:07 exsemt

Got it, that sounds like a nice addition 🙂 Feel free to come up with a PR if you're interested in playing with the gem, otherwise I'll take a look at it next week

DmitryTsepelev avatar Jul 12 '19 15:07 DmitryTsepelev

Hi @exsemt!

I've added a couple of tests for nested attributes, and it looks like for your case

concept.update(id: 1, name: "name", values: [{ name: "name }])

or

concept = Concept.last
concept.values = [ConceptValue.new(name: "name)]
concept.values

should work of the box. What usecase am I missing here?

DmitryTsepelev avatar Jul 18 '19 11:07 DmitryTsepelev

Correct, that works, but it does not work as an Active Record Nested Attributes so values_attributes:

concept.update(id: 1, name: "name", values_attributes: [{ name: "name }])

exsemt avatar Jul 24 '19 14:07 exsemt

Here we go https://github.com/DmitryTsepelev/store_model/pull/17 - could you please try it out before I merge it in?

DmitryTsepelev avatar Jul 24 '19 14:07 DmitryTsepelev

Released 0.4.0 with accept_nested_attributes_for support

DmitryTsepelev avatar Jul 26 '19 08:07 DmitryTsepelev

Thanks! Sorry that took so long time to check it, it works fine for .to_type association, but it does not work for a .to_array_type, because you get from HTML form a hash with a key as counter of association object and value - the object hash. e.g.:

class Concept
  include StoreModel::Model

  attribute :id, :integer
  attribute :name, :string
  attribute :values, ConceptValue.to_array_type
end

# does not work
concept.update(id: 1, name: "name", values_attributes: [{ "0" => { "name" => "name 1" }}, { "1" => { "name" => "name 2" }}])

exsemt avatar Jul 29 '19 13:07 exsemt

Here is a PR with a possible fix. The only thing is that in Rails only Hash and Array are accepted, so the param should be either { "0" => { "name" => "name 1" }, "1" => { "name" => "name 2" }] or [{ "name" => "name 1" }, { "1" => { "name" => "name 2" }]. Could you please make sure your form sends [{ "0" => { "name" => "name 1" }}, { "1" => { "name" => "name 2" }}]?

DmitryTsepelev avatar Jul 29 '19 15:07 DmitryTsepelev

Thx! Works! 👍

exsemt avatar Jul 29 '19 15:07 exsemt

I tried adding validatation on nested attributes but it gave me the error "NoMethodError (undefined method `type_for_attribute' for ...)"

class Form
  include StoreModel::Model

  attribute :id, :integer
  attribute :for, :string
  attribute :inputs, FormInput.to_array_type

  validates :id, :for, presence: true
  validates :inputs, store_model: true
end

class FormInput
  include StoreModel::Model

  attribute :label, :string
  attribute :value, :string

  validates :label, :value, presence: true
end

jsice avatar Jul 29 '19 17:07 jsice

Hi @jsice!

Thanks for the report, I'll do my best to investigate this issue later this week

DmitryTsepelev avatar Jul 29 '19 20:07 DmitryTsepelev

Rolled out 0.4.1 with fixes for both issues @exsemt @jsice

DmitryTsepelev avatar Jul 30 '19 21:07 DmitryTsepelev

Thanks!

jsice avatar Jul 31 '19 01:07 jsice

Hey all, firstly this is a really cool gem and it will hopefully make my life way easier! I've just started playing around with it and have the following set up

class Pathogen < ActiveRecord::Base
  attribute :configuration, Configuration.to_type
end

class Configuration
  include StoreModel::Model

  accepts_nested_attributes_for :susceptibility

  attribute :susceptibility, Susceptibility.to_array_type

end

class Susceptibility
  include StoreModel::Model

  attribute :icon, :string
  attribute :link, :string
  attribute :name, :string
  attribute :value, :string
  attribute :render_method, :string
end

When I submit the update form on the pathogen my params look like

> pathogen_params[:configuration]
=> <ActionController::Parameters {"susceptibility_attributes"=><ActionController::Parameters {"0"=><ActionController::Parameters {"value"=>"Edit one", "name"=>"General susceptibility", "icon"=>"", "link"=>"", "render_method"=>"string"} permitted: true>, "1"=><ActionController::Parameters {"value"=>"Edit two", "name"=>"Antibiogram footnotes", "icon"=>"", "link"=>"", "render_method"=>"string"} permitted: true>} permitted: true>} permitted: true>

but when I call update on the pathogen model it does not save the nested susceptibility attributes and instead returns just nil

> Pathogen.find(1898).configuration
  Pathogen Load (1.2ms)  SELECT  "pathogens".* FROM "pathogens" WHERE "pathogens"."id" = $1 LIMIT $2 /*application:Spectrum*/  [["id", 1898], ["LIMIT", 1]]
=> #<Configuration susceptibility: nil, general_information: nil>

I'm thinking I am just doing something small wrong...any help would be greatly appreciated!

evanshabsove avatar Dec 05 '19 21:12 evanshabsove

Hey @evanshabsove, I'm not sure it will help, but just in case, take a look here: https://github.com/DmitryTsepelev/store_model/issues/41

I didn't even know there is an accept_nested_attributes_for support! Gotta play around with it :)

flvrone avatar Dec 05 '19 21:12 flvrone

I ended up figuring it out! I was trying to be too cute with it. We use Inherited Resources (https://github.com/activeadmin/inherited_resources) and I was hoping the update! method in that would magically take care of everything, but I was wishing too hard. Changing the assignment to just

@pathogen.configuration = configuration_params[:configuration].to_hash

Fixed everything. @FunkyloverOne thanks for linking me to the issue thread!

Looking at this though I wonder if I just remove the :configuration part of the param I can be cute with it...anyways a discussion for another place.

evanshabsove avatar Dec 05 '19 22:12 evanshabsove

I know this is an old issue, but I stumbled upon an error when using shoulda matchers:

     Failure/Error: it { is_expected.to accept_nested_attributes_for(:parcels) }

     NoMethodError:
       undefined method `nested_attributes_options' for SomeModel:Class
     # /usr/local/bundle/gems/shoulda-matchers-5.1.0/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb:196:in `model_config'
     # /usr/local/bundle/gems/shoulda-matchers-5.1.0/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb:192:in `config'
     # /usr/local/bundle/gems/shoulda-matchers-5.1.0/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb:152:in `exists?'
     # /usr/local/bundle/gems/shoulda-matchers-5.1.0/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb:121:in `matches?'

This leads to this line https://github.com/thoughtbot/shoulda-matchers/blob/main/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb#L196

Is there something missing inside store model?

23tux avatar Apr 21 '22 13:04 23tux

Right, this method was not ported 😞

DmitryTsepelev avatar Apr 25 '22 20:04 DmitryTsepelev

Is there any chance, this method gets ported in the next release?

23tux avatar Jun 09 '22 13:06 23tux

Sure, I just need a volounteer and will be happy to review the PR! 🙂

DmitryTsepelev avatar Jun 10 '22 12:06 DmitryTsepelev

any updates?

alexandreh92 avatar Feb 20 '24 01:02 alexandreh92