Closed Antiarchitect closed 8 years ago
That's strange. Decimals are part of the test suite :/
I'll see what I can do, but a reproduction gist would tremendously help.
You could base it off Rails's repro template: https://github.com/rails/rails/blob/adfb823af52d368fa4d88731a9809a314ad884ad/guides/bug_report_templates/active_record_gem.rb
@byroot Here you are. This perfectly reproduces my real problem.
begin
require 'bundler/inline'
rescue LoadError => e
$stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler'
raise e
end
gemfile(true) do
source 'https://rubygems.org'
# Activate the gem you are reporting the issue against.
gem 'activerecord', '4.2.4'
gem 'sqlite3'
gem 'activerecord-typedstore', '0.6.1'
end
require 'active_record'
require 'minitest/autorun'
require 'logger'
# Ensure backward compatibility with Minitest 4
Minitest::Test = MiniTest::Unit::TestCase unless defined?(Minitest::Test)
# 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, force: true do |t|
t.text :data
end
end
class Post < ActiveRecord::Base
module DummyCoder
extend self
def load(data)
data || {}
end
def dump(data)
data || {}
end
end
typed_store :meta, coder: DummyCoder do |s|
s.decimal :value
end
end
class BugTest < Minitest::Test
def test_association_stuff
post = Post.create!(value: 36.6)
post.comments << Comment.create!
assert_equal 1, post.comments.count
end
end
This is my output:
Fetching gem metadata from https://rubygems.org/...........
Fetching version metadata from https://rubygems.org/..
Resolving dependencies...
Using i18n 0.7.0
Using json 1.8.3
Using minitest 5.8.1
Using thread_safe 0.3.5
Using tzinfo 1.2.2
Using activesupport 4.2.4
Using builder 3.2.2
Using activemodel 4.2.4
Using arel 6.0.3
Using activerecord 4.2.4
Using activerecord-typedstore 0.6.1
Using sqlite3 1.3.10
Using bundler 1.10.3
-- create_table(:posts, {:force=>true})
D, [2015-09-24T21:34:58.259118 #13651] DEBUG -- : (0.2ms) CREATE TABLE "posts" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "data" text)
-> 0.0022s
Run options: --seed 24322
# Running:
E
Finished in 0.003298s, 303.2433 runs/s, 0.0000 assertions/s.
1) Error:
BugTest#test_association_stuff:
NoMethodError: undefined method `accessor' for #<ActiveRecord::Type::Value:0x00000003068260>
/home/andrey/.rvm/gems/ruby-2.2.2/gems/activerecord-4.2.4/lib/active_record/store.rb:132:in `store_accessor_for'
/home/andrey/.rvm/gems/ruby-2.2.2/gems/activerecord-4.2.4/lib/active_record/store.rb:121:in `read_store_attribute'
/home/andrey/.rvm/gems/ruby-2.2.2/gems/activerecord-typedstore-0.6.1/lib/active_record/typed_store/extension.rb:116:in `write_store_attribute'
/home/andrey/.rvm/gems/ruby-2.2.2/gems/activerecord-4.2.4/lib/active_record/store.rb:86:in `block (3 levels) in store_accessor'
/home/andrey/.rvm/gems/ruby-2.2.2/gems/activerecord-4.2.4/lib/active_record/attribute_assignment.rb:54:in `public_send'
/home/andrey/.rvm/gems/ruby-2.2.2/gems/activerecord-4.2.4/lib/active_record/attribute_assignment.rb:54:in `_assign_attribute'
/home/andrey/.rvm/gems/ruby-2.2.2/gems/activerecord-4.2.4/lib/active_record/attribute_assignment.rb:41:in `block in assign_attributes'
/home/andrey/.rvm/gems/ruby-2.2.2/gems/activerecord-4.2.4/lib/active_record/attribute_assignment.rb:35:in `each'
/home/andrey/.rvm/gems/ruby-2.2.2/gems/activerecord-4.2.4/lib/active_record/attribute_assignment.rb:35:in `assign_attributes'
/home/andrey/.rvm/gems/ruby-2.2.2/gems/activerecord-4.2.4/lib/active_record/core.rb:564:in `init_attributes'
/home/andrey/.rvm/gems/ruby-2.2.2/gems/activerecord-4.2.4/lib/active_record/core.rb:281:in `initialize'
/home/andrey/.rvm/gems/ruby-2.2.2/gems/activerecord-4.2.4/lib/active_record/inheritance.rb:61:in `new'
/home/andrey/.rvm/gems/ruby-2.2.2/gems/activerecord-4.2.4/lib/active_record/inheritance.rb:61:in `new'
/home/andrey/.rvm/gems/ruby-2.2.2/gems/activerecord-4.2.4/lib/active_record/persistence.rb:50:in `create!'
bug.rb:54:in `test_association_stuff'
1 runs, 0 assertions, 0 failures, 1 errors, 0 skips
t.text :data
typed_store :meta
:data != :meta
. So I think it's simply due to a typo. Please re-open if I'm wrong.
@byroot Reproduced more thoroughly. Seems like it's because of delegate.
begin
require 'bundler/inline'
rescue LoadError => e
$stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler'
raise e
end
gemfile(true) do
source 'https://rubygems.org'
# Activate the gem you are reporting the issue against.
gem 'activerecord', '4.2.4'
gem 'sqlite3'
gem 'activerecord-typedstore', '0.6.1'
end
require 'active_record'
require 'minitest/autorun'
require 'logger'
# Ensure backward compatibility with Minitest 4
Minitest::Test = MiniTest::Unit::TestCase unless defined?(Minitest::Test)
# 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, force: true do |t|
t.integer :author_id
t.text :data
end
create_table :authors, force: true do |t|
end
end
class Post < ActiveRecord::Base
belongs_to :author
end
class Author < ActiveRecord::Base
has_one :post
module DummyCoder
extend self
def load(data)
data || {}
end
def dump(data)
data || {}
end
end
delegate :data, :data_will_change!, :data_changed?, to: :bound_post
def bound_post
@bound_post ||= build_post
end
typed_store :data, coder: DummyCoder do |s|
s.decimal :value
end
end
class BugTest < Minitest::Test
def test_association_stuff
Author.create!(value: 36.6)
assert_equal 1, Author.count
end
end
Oh! I see. You can't define a store on something that isn't a real attribute. TypedStore need to read the column information from ActiveRecord.
If you really wish to delegate this column, you can still do it this way:
begin
require 'bundler/inline'
rescue LoadError => e
$stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler'
raise e
end
gemfile(true) do
source 'https://rubygems.org'
# Activate the gem you are reporting the issue against.
gem 'activerecord', '4.2.4'
gem 'sqlite3'
gem 'byebug'
gem 'activerecord-typedstore', '0.6.1'
end
require 'active_record'
require 'minitest/autorun'
require 'logger'
# Ensure backward compatibility with Minitest 4
Minitest::Test = MiniTest::Unit::TestCase unless defined?(Minitest::Test)
# 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, force: true do |t|
t.integer :author_id
t.text :data
end
create_table :authors, force: true do |t|
end
end
class Post < ActiveRecord::Base
belongs_to :author
typed_store :data do |s|
s.decimal :value
end
end
class Author < ActiveRecord::Base
has_one :post
delegate :value, :value=, to: :bound_post
def bound_post
@bound_post ||= build_post
end
end
class BugTest < Minitest::Test
def test_association_stuff
Author.create!(value: 36.6)
assert_equal 1, Author.count
end
end
Exactly, this is my current workaround. But this only works when your bound model class and parent class is one to one.
Think for normal situations that is not a bug.
Rails 4.2.4, activerecord-typedstore 0.6.1. When I try to instanciate record with decimal typed value described. I get this: