Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

undefined method 'accessor' for ActiveRecord::Type::Value #33

Closed
Antiarchitect opened this issue Sep 24, 2015 · 7 comments
Closed

undefined method 'accessor' for ActiveRecord::Type::Value #33

Antiarchitect opened this issue Sep 24, 2015 · 7 comments

Comments

@Antiarchitect
Copy link

Rails 4.2.4, activerecord-typedstore 0.6.1. When I try to instanciate record with decimal typed value described. I get this:

NoMethodError: undefined method `accessor' for #<ActiveRecord::Type::Value:0x0000000a097270>
    from /home/andrey/.rvm/gems/ruby-2.2.3@medm/gems/activerecord-4.2.4/lib/active_record/store.rb:132:in `store_accessor_for'
    from /home/andrey/.rvm/gems/ruby-2.2.3@medm/gems/activerecord-4.2.4/lib/active_record/store.rb:121:in `read_store_attribute'
    from /home/andrey/PROJECTS/activerecord-typedstore/lib/active_record/typed_store/extension.rb:118:in `write_store_attribute'
@byroot
Copy link
Owner

byroot commented Sep 24, 2015

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

@Antiarchitect
Copy link
Author

@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

@byroot
Copy link
Owner

byroot commented Sep 24, 2015

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 byroot closed this as completed Sep 24, 2015
@Antiarchitect
Copy link
Author

@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

@byroot
Copy link
Owner

byroot commented Sep 24, 2015

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

@Antiarchitect
Copy link
Author

Exactly, this is my current workaround. But this only works when your bound model class and parent class is one to one.

@Antiarchitect
Copy link
Author

Think for normal situations that is not a bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants