NoMethodError: undefined method `cast' for nil:NilClass after set value to field
havran opened this issue · 3 comments
Hello. Thanks for great gem!
I have weird problem in my production app.
If i try set value for field url in new or stored model, i always get NoMethodError: undefined method `cast' for nil:NilClass - but only for one field from all typed_Store defined fields.
Rails version is 5.x
In development mode works all ok.
module Space
module ProjectItems
class Page < ::Space::ProjectItem
...
typed_store :data, coder: JsonCoder do |d|
d.string :valid_for_region, array: true, default: []
d.string :category, default: nil
d.string :tag, array: true, default: []
d.string :hashtag, default: nil
d.string :url, default: nil # URL
end
...
end
end
end
irb(main):044:0* p = Space::ProjectItems::Page.new
=> #<Space::ProjectItems::Page id: nil, project_id: nil, item_type: "page", title: nil, description: nil, public: false, valid_from: nil, valid_to: nil, image_data: nil, data_location: {"lat"=>nil, "lon"=>nil, "zoom"=>nil, "formatted_address"=>nil}, data_zones: {"zones"=>[], "use_location_from_zones"=>false}, data: {"valid_for_region"=>[], "category"=>nil, "tag"=>[], "hashtag"=>nil, "url"=>nil}, created_at: nil, updated_at: nil, code: nil>
irb(main):045:0> p.data
=> {"valid_for_region"=>[], "category"=>nil, "tag"=>[], "hashtag"=>nil, "url"=>nil}
irb(main):046:0> p.category = 'a'
=> "a"
irb(main):047:0> p.hashtag = 'b'
=> "b"
irb(main):048:0> p.url = 'c'
NoMethodError: undefined method `cast' for nil:NilClass
from /home/deployer/uidis/shared/bundle/ruby/2.3.0/gems/activerecord-typedstore-1.1.1/lib/active_record/typed_store/extension.rb:74:in `write_store_attribute'
from /home/deployer/uidis/shared/bundle/ruby/2.3.0/gems/activerecord-5.0.3/lib/active_record/store.rb:91:in `block (3 levels) in store_accessor'
from (irb):48
from /home/deployer/uidis/shared/bundle/ruby/2.3.0/gems/railties-5.0.3/lib/rails/commands/console.rb:65:in `start'
from /home/deployer/uidis/shared/bundle/ruby/2.3.0/gems/railties-5.0.3/lib/rails/commands/console_helper.rb:9:in `start'
from /home/deployer/uidis/shared/bundle/ruby/2.3.0/gems/railties-5.0.3/lib/rails/commands/commands_tasks.rb:78:in `console'
from /home/deployer/uidis/shared/bundle/ruby/2.3.0/gems/railties-5.0.3/lib/rails/commands/commands_tasks.rb:49:in `run_command!'
from /home/deployer/uidis/shared/bundle/ruby/2.3.0/gems/railties-5.0.3/lib/rails/commands.rb:18:in `<top (required)>'
from bin/rails:9:in `require'
from bin/rails:9:in `<main>'
I try refactor my code. Before model Page is inherited from base model ProjectItems (models shared same database table, but i want different fields in store on every model). Now i have common model settings in concern and problem with set value on fields disappear.
I am still curious with this but i think this is burried too deep for my knowledge :-/
Could you try reproduce the issue with a minimal app?
I have the same problem which present itself only when model inheritance is used and descendant defines it's own typed_store
. This has an unexpected effect of overriding typed_store
value for same store_attribute
for all class hierarchy and ancestors in particular.
For example this code results in all animals having gills:
class Animal < ApplicationRecord
typed_store :data do |d|
d.integer :ears_count, default: 2
end
end
class Fish < Animal
typed_store :data do |d|
d.boolean :has_gills, default: true
end
end
Animal.new.has_gills
# => true
Animal.new.ears_count
# NoMethodError: undefined method `ears_count'
Desired behaviour for me is this:
class Animal < ApplicationRecord
typed_store :data do |d|
d.integer :ears_count, default: 2
end
end
class Bear < Animal
end
class Fish < Animal
typed_store :data do |d|
d.boolean :has_gills, default: true
end
end
Animal.new.ears_count
# => 2
Animal.new.has_gills
# NoMethodError: undefined method `has_gills'
Bear.new.ears_count
# => 2
Bear.new.has_gills
# NoMethodError: undefined method `has_gills'
Fish.new.has_gills
# => true
Fish.new.ears_count
# NoMethodError: undefined method `ears_count'
There are one possible solution in previous commit. What are your thoughts?