Comments (6)
@maniSHarma7575 I'm not sure about that. Looking at the code, the original store
call is needed to set up the serializer on an existing column, and I think this is the underlying issue. (I'm using Rails edge in my analysis.) Regardless I think store_accessor
should detect when there's no serializer associated and raise an error.
from rails.
Now that you know how to reproduce, you can use git bisect to find which change makes the exception to happen. Can you try that?
from rails.
@joesiewert, I've drafted the script to replicate the behavior.
Rails version: 6.0.0
Ruby version: ruby 2.7.8p225 (2023-03-30 revision 1f4d455848) [arm64-darwin22]
Even with Rails 6.0.0, this is breaking. I believe there's a valid reason: in the migration, we haven't included the creation of a metadata
column.
Adding the following line to the migration script should resolve the issue.
t.json :metadata
I was looking at hashicorp/vault-rails#138 and haven't found any migration with adding the column features
into the database.
# frozen_string_literal: true
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
gem "rails", "=6.0.0"
# If you want to test against edge Rails replace the previous line with this:
# gem "rails", github: "rails/rails", branch: "main"
gem "sqlite3", "~> 1.4"
end
require "active_record"
require "minitest/autorun"
require "logger"
# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Schema.define do
create_table :posts do |t|
t.string :title
t.text :content
t.timestamps
end
end
class Post < ActiveRecord::Base
store_accessor :metadata, [:likes_count, :comments_count, :tags]
end
class BugTest < Minitest::Test
def test_store_accessors
post = Post.new(title: "Example Post", content: "This is an example post")
post.likes_count = 10
post.comments_count = 5
post.tags = ["ruby", "rails", "example"]
post.save
post = Post.last
assert_equal 10, post.likes_count
assert_equal 5, post.comments_count
assert_equal %w[ruby rails example], post.tags
end
end
Output:
E
Error:
BugTest#test_store_accessors:
NoMethodError: undefined method `accessor' for #<ActiveModel::Type::Value:0x000000011dd9e4a0>
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/activerecord-6.0.0/lib/active_record/store.rb:217:in `store_accessor_for'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/activerecord-6.0.0/lib/active_record/store.rb:212:in `write_store_attribute'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/activerecord-6.0.0/lib/active_record/store.rb:136:in `block (3 levels) in store_accessor'
51699.rb:38:in `test_store_accessors'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest/test.rb:95:in `block (3 levels) in run'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest/test.rb:192:in `capture_exceptions'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest/test.rb:90:in `block (2 levels) in run'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:324:in `time_it'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest/test.rb:89:in `block in run'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:423:in `on_signal'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest/test.rb:240:in `with_info_handler'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest/test.rb:88:in `run'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:1138:in `run_one_method'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:389:in `run_one_method'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:376:in `block (2 levels) in run'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:375:in `each'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:375:in `block in run'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:423:in `on_signal'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:410:in `with_info_handler'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:374:in `run'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:206:in `block in __run'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:206:in `map'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:206:in `__run'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:162:in `run'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:86:in `block in autorun'
rails test 51699.rb:36
@rafaelfranca when we run this script with creating the column metadata
as an text instead of the json
the script throws an error detailed below. Is this desired behaviour?
t.text :metadata
# Running:
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/activemodel-6.0.0/lib/active_model/type/integer.rb:13: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/activemodel-6.0.0/lib/active_model/type/value.rb:8: warning: The called method `initialize' is defined here
E
Error:
BugTest#test_store_accessors:
NoMethodError: undefined method `accessor' for #<ActiveRecord::Type::Text:0x0000000134d43660>
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/activerecord-6.0.0/lib/active_record/store.rb:217:in `store_accessor_for'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/activerecord-6.0.0/lib/active_record/store.rb:212:in `write_store_attribute'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/activerecord-6.0.0/lib/active_record/store.rb:136:in `block (3 levels) in store_accessor'
51699.rb:39:in `test_store_accessors'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest/test.rb:95:in `block (3 levels) in run'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest/test.rb:192:in `capture_exceptions'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest/test.rb:90:in `block (2 levels) in run'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:324:in `time_it'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest/test.rb:89:in `block in run'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:423:in `on_signal'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest/test.rb:240:in `with_info_handler'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest/test.rb:88:in `run'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:1138:in `run_one_method'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:389:in `run_one_method'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:376:in `block (2 levels) in run'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:375:in `each'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:375:in `block in run'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:423:in `on_signal'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:410:in `with_info_handler'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:374:in `run'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:206:in `block in __run'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:206:in `map'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:206:in `__run'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:162:in `run'
/Users/manishsharma/.rvm/gems/ruby-2.7.8/gems/minitest-5.22.3/lib/minitest.rb:86:in `block in autorun'
from rails.
I think the issue here is that this code:
store_accessor :metadata, [:likes_count, :comments_count, :tags]
should be
store :metadata, accessors: [:likes_count, :comments_count, :tags]
I wonder if store_accessor
should raise an exception if it's not going to do what the user expects? I would need to dig deeper to understand ActiveRecord::Store before speculating more.
from rails.
ActiveRecord
@flavorjones I don't think we should have any issues with the code regarding how we use it, as mentioned here:
rails/activerecord/lib/active_record/store.rb
Lines 40 to 72 in 343e781
store_accessor
provides an functionality to Add additional accessors to an existing store (From Parent Class) through store_accessor
.
I tried the code below as well, and we're encountering the same error.
store :metadata, accessors: [:likes_count, :comments_count, :tags]
Error:
BugTest#test_store_accessors:
NoMethodError: undefined method `accessor' for #<ActiveModel::Type::Value:0x000000011ad3c988>
If we add the column metadata to the migration and we also need to add the coder: JSON
, the problem is solved.
ActiveRecord::Schema.define do
create_table :posts do |t|
t.string :title
t.text :content
t.text :metadata #Adding the column metadata solve the problem
t.timestamps
end
end
store :metadata, accessors: [:likes_count, :comments_count, :tags], coder: JSON
from rails.
Yeah, @flavorjones you are correct.
Here is the observered behaviour with
Ruby: ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [arm64-darwin23]
Rails: Rails Edge
1. Not creating the metadata column in migration and initializing store as following:
store :metadata, accessors: [:likes_count, :comments_count, :tags]
Output:
Finished in 0.011299s, 88.5034 runs/s, 88.5034 assertions/s.
1) Failure:
BugTest#test_store_accessors [51699.rb:45]:
Expected: 10
Actual: nil
1 runs, 1 assertions, 1 failures, 0 errors, 0 skips
2. Creating metadata column in migration and initializing store as following:
t.text :metadata
store :metadata, accessors: [:likes_count, :comments_count, :tags]
Output:
Run options: --seed 8267
# Running:
D, [2024-05-06T09:35:58.280339 #2983] DEBUG -- : TRANSACTION (0.0ms) begin transaction
D, [2024-05-06T09:35:58.280448 #2983] DEBUG -- : Post Create (0.1ms) INSERT INTO "posts" ("title", "content", "metadata", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) RETURNING "id" [["title", "Example Post"], ["content", "This is an example post"], ["metadata", "---\nlikes_count: 10\ncomments_count: 5\ntags:\n- ruby\n- rails\n- example\n"], ["created_at", "2024-05-06 04:05:58.279740"], ["updated_at", "2024-05-06 04:05:58.279740"]]
D, [2024-05-06T09:35:58.280578 #2983] DEBUG -- : TRANSACTION (0.0ms) commit transaction
D, [2024-05-06T09:35:58.284738 #2983] DEBUG -- : Post Load (0.0ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."id" DESC LIMIT ? [["LIMIT", 1]]
.
Finished in 0.011449s, 87.3439 runs/s, 262.0316 assertions/s.
1 runs, 3 assertions, 0 failures, 0 errors, 0 skips
3. Not creating column and store initialization as follows:
store_accessor :metadata, [:likes_count, :comments_count, :tags]
Output:
Run options: --seed 4507
# Running:
E
Finished in 0.004929s, 202.8809 runs/s, 0.0000 assertions/s.
1) Error:
BugTest#test_store_accessors:
NoMethodError: undefined method `accessor' for an instance of ActiveModel::Type::Value
rails/activerecord/lib/active_record/store.rb:220:in `store_accessor_for'
rails/activerecord/lib/active_record/store.rb:215:in `write_store_attribute'
rails/activerecord/lib/active_record/store.rb:139:in `block (3 levels) in store_accessor'
51699.rb:40:in `test_store_accessors'
1 runs, 0 assertions, 0 failures, 1 errors, 0 skips
4. Creating column and store initialization as follows:
t.text :metadata
store_accessor :metadata, [:likes_count, :comments_count, :tags]
Output:
Run options: --seed 31357
# Running:
E
Finished in 0.005465s, 182.9826 runs/s, 0.0000 assertions/s.
1) Error:
BugTest#test_store_accessors:
NoMethodError: undefined method `accessor' for an instance of ActiveRecord::Type::Text
rails/activerecord/lib/active_record/store.rb:220:in `store_accessor_for'
rails/activerecord/lib/active_record/store.rb:215:in `write_store_attribute'
rails/activerecord/lib/active_record/store.rb:139:in `block (3 levels) in store_accessor'
51699.rb:40:in `test_store_accessors'
1 runs, 0 assertions, 0 failures, 1 errors, 0 skips
from rails.
Related Issues (20)
- Possible race condition in postgresql type_map initialization HOT 8
- rspec tests won't after upgrading from rails 7.1.2 to 7.1.3.2: can't modify frozen Array when requiring environment file HOT 2
- form_with reverting to HTML processing only HOT 5
- Inaccurate docs/comments about ActiveStorage video previewer defaults could be improved HOT 4
- Inconsistent model state when dumped and loaded with Marshal version 7.1 HOT 4
- ActiveRecord connection is checked out/retained despite setting `config.active_record.permanent_connection_checkout = :disallowed` HOT 4
- Default Active Support Logger in Addition to Custom Logger in Rails 7.1 x BroadcastLogger Class in Development environment HOT 1
- Aws::Rails::SqsActiveJob#execute captures StandardError which is too wide HOT 1
- AppGeneratorTest fails because `Could not find gem 'kamal' in locally installed gems.` HOT 1
- `has_one :through` associations ignore preloaded records
- loading credentials key HOT 5
- Different timestamps behaviour with InsertAll HOT 3
- Activerecord: Insert fails on composed_primary_key model with id as not null Identity column
- procfile causes failure on Rails 8.0 HOT 8
- Rails 7.1 changes established database connection after calling `rails db:test:prepare` for multi-database apps HOT 4
- Storage folder seems like it is sometimes not needed
- Storage folder sometimes doesn't need Kamal configuration in Rails 8.0.0.alpha HOT 1
- Content-Type parsing breaks on valid test cases HOT 4
- PostgreSQL Apache AGE Rails (GraphDB driver questions / problems) HOT 7
- s
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rails.