appfolio / store_base_sti_class Goto Github PK
View Code? Open in Web Editor NEWModifies ActiveRecord 4+ with the ability to store the actual class (instead of the base class) in polymorphic _type columns when using STI
License: MIT License
Modifies ActiveRecord 4+ with the ability to store the actual class (instead of the base class) in polymorphic _type columns when using STI
License: MIT License
The initializer doesn't seem to work Rails 4.0.0.
Installing the gem happens. Adding the following line as an initializer
ActiveRecord::Base.store_base_sti_class = false
triggers this error:
Users/robin/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-4.0.0.beta1/lib/active_record/dynamic_matchers.rb:22:in `method_missing': undefined method `store_base_sti_class=' for ActiveRecord::Base:Class (NoMethodError)
from /Users/robin/code/rails/white_design/config/initializers/sti_class.rb:1:in `<top (required)>'
from /Users/robin/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-4.0.0.beta1/lib/active_support/dependencies.rb:222:in `load'
from /Users/robin/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-4.0.0.beta1/lib/active_support/dependencies.rb:222:in `block in load'
from /Users/robin/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-4.0.0.beta1/lib/active_support/dependencies.rb:213:in `load_dependency'
from /Users/robin/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-4.0.0.beta1/lib/active_support/dependencies.rb:222:in `load'
from /Users/robin/.rvm/gems/ruby-2.0.0-p0/gems/railties-4.0.0.beta1/lib/rails/engine.rb:608:in `block (2 levels) in <class:Engine>'
from /Users/robin/.rvm/gems/ruby-2.0.0-p0/gems/railties-4.0.0.beta1/lib/rails/engine.rb:607:in `each'
from /Users/robin/.rvm/gems/ruby-2.0.0-p0/gems/railties-4.0.0.beta1/lib/rails/engine.rb:607:in `block in <class:Engine>'
from /Users/robin/.rvm/gems/ruby-2.0.0-p0/gems/railties-4.0.0.beta1/lib/rails/initializable.rb:30:in `instance_exec'
from /Users/robin/.rvm/gems/ruby-2.0.0-p0/gems/railties-4.0.0.beta1/lib/rails/initializable.rb:30:in `run'
from /Users/robin/.rvm/gems/ruby-2.0.0-p0/gems/railties-4.0.0.beta1/lib/rails/initializable.rb:55:in `block in run_initializers'
from /Users/robin/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/tsort.rb:150:in `block in tsort_each'
from /Users/robin/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/tsort.rb:183:in `block (2 levels) in each_strongly_connected_component'
from /Users/robin/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/tsort.rb:210:in `block (2 levels) in each_strongly_connected_component_from'
from /Users/robin/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/tsort.rb:219:in `each_strongly_connected_component_from'
from /Users/robin/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/tsort.rb:209:in `block in each_strongly_connected_component_from'
from /Users/robin/.rvm/gems/ruby-2.0.0-p0/gems/railties-4.0.0.beta1/lib/rails/initializable.rb:44:in `each'
from /Users/robin/.rvm/gems/ruby-2.0.0-p0/gems/railties-4.0.0.beta1/lib/rails/initializable.rb:44:in `tsort_each_child'
from /Users/robin/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/tsort.rb:203:in `each_strongly_connected_component_from'
from /Users/robin/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/tsort.rb:182:in `block in each_strongly_connected_component'
from /Users/robin/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/tsort.rb:180:in `each'
from /Users/robin/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/tsort.rb:180:in `each_strongly_connected_component'
from /Users/robin/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/tsort.rb:148:in `tsort_each'
from /Users/robin/.rvm/gems/ruby-2.0.0-p0/gems/railties-4.0.0.beta1/lib/rails/initializable.rb:54:in `run_initializers'
from /Users/robin/.rvm/gems/ruby-2.0.0-p0/gems/railties-4.0.0.beta1/lib/rails/application.rb:213:in `initialize!'
from /Users/robin/.rvm/gems/ruby-2.0.0-p0/gems/railties-4.0.0.beta1/lib/rails/railtie/configurable.rb:30:in `method_missing'
from /Users/robin/code/rails/white_design/config/environment.rb:5:in `<top (required)>'
from /Users/robin/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-4.0.0.beta1/lib/active_support/dependencies.rb:228:in `require'
from /Users/robin/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-4.0.0.beta1/lib/active_support/dependencies.rb:228:in `block in require'
from /Users/robin/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-4.0.0.beta1/lib/active_support/dependencies.rb:213:in `load_dependency'
from /Users/robin/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-4.0.0.beta1/lib/active_support/dependencies.rb:228:in `require'
from /Users/robin/.rvm/gems/ruby-2.0.0-p0/gems/railties-4.0.0.beta1/lib/rails/application.rb:187:in `require_environment!'
from /Users/robin/.rvm/gems/ruby-2.0.0-p0/gems/railties-4.0.0.beta1/lib/rails/commands.rb:63:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4:in `<main>'
Is this because of major updates on ActiveRecord or can I easily fix this?
Using the updateForRails41
branch, I got this error after adding the initializer:
undefined method store_base_sti_class=' for ActiveRecord::Base:Class'
Is there a way to fix it ?
Hi, I've just updated to Rails 5.2.5 from 5.2.4.4 and came across an issue.
Starting the app gives this error:
NameError:
undefined local variable or method `options_for_through_record' for #<ActiveRecord::Associations::HasManyThroughAssociation:0x00007f23ccc9ce20>
# /usr/local/bundle/gems/store_base_sti_class-2.0.2/lib/store_base_sti_class_for_5_2.rb:138:in `build_through_record'
I took a look into it and it appears to be because of
where the gem has a special case for5.2.4
, which doesn't match for 5.2.5
and so we drop into the else
branch.
Patching it locally to catch 5.2.5
as well appears to work with our test suite
I ran into a problem while trying out this branch of paper_trail (and a couple related ones): paper-trail-gem/paper_trail#1143. (It's not in master yet, but it could end up there soon)
When using store_base_sti_class
, you can't find PaperTrail "destroy" versions through the versions
association because store_base_sti_class
causes the has_many :versions
association to look for version records where(item_type: subclass)
instead of the Rails default of where(item_type: base_class)
.
Non-destroy versions still work as expected with store_base_sti_class
, since those get created through a standard has_many
, which means item_type
gets set to the subclass due to store_base_sti_class
:
lib/paper_trail/record_trail.rb
=> 129: versions_assoc = @record.send(@record.class.versions_association_name)
130: version = versions_assoc.create(data)
The problem is that when paper_trail creates "destroy" versions,,it doesn't go through the versions
association โ it hard-codes it to always store the base_class
in item_type
โ such that the ActiveRecord hacks that store_base_sti_class
provides have no effect.
So if you do this:
record.destroy
record.versions.last.event
you'll find that the destroy event is not there!
Here's the code used for creating destroy versions:
lib/paper_trail/events/destroy.rb
12: # Return attributes of nascent `Version` record.
13: #
14: # @api private
15: def data
=> 16: data = {
17: item_id: @record.id,
18: item_type: @record.class.base_class.name,
lib/paper_trail/record_trail.rb
99: data = event.data.merge(data_for_destroy)
100:
=> 101: version = @record.class.paper_trail.version_class.create(data)
You can see it doesn't go through versions_assoc
like it does for update events. It just calls Version.create
directly.
uninitialized constant ActiveRecord::Associations::JoinDependency::JoinPart (NameError)
I really like that this gem actually stores the correct class type in the db for STI. Really excellent stuff. But I definitely found a problem regarding ActiveRecord::NestedAttributes and the ability to do this trivial call below:
(Hopefully this is really all you need to see and troubleshoot the problem)
class ContentGroup < ActiveRecord::Base
attr_protected
has_many :bodies, :dependent=>:destroy
accepts_nested_attributes_for :bodies
end
class Content < ActiveRecord::Base
attr_protected
has_one :sort_item, :as=>:sortable
belongs_to :content_group, :dependent=>:destroy
accepts_nested_attributes_for :sort_item
end
class Body < Content
attr_protected
end
class SortItem < ActiveRecord::Base
attr_protected
belongs_to :sortable, :polymorphic=>true
end
p = {"sort_item_attributes"=>{"position"=>"1"}}
b = Body.new(p)
=> Body id: nil, content_group_id: nil, type: "Body"
p = {"bodies_attributes"=>{"sort_item_attributes"=>{"position"=>"1"}}}
cg = ContentGroup.new(p)
ActiveRecord::UnknownAttributeError: unknown attribute: position
from /.rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.13/lib/active_record/attribute_assignment.rb:88:inblock in assign_attributes' from /.rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.13/lib/active_record/attribute_assignment.rb:78:in
each'
from /.rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.13/lib/active_record/attribute_assignment.rb:78:inassign_attributes' from /.rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.13/lib/active_record/base.rb:498:in
initialize'
from /.rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.13/lib/active_record/reflection.rb:183:innew' from /.rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.13/lib/active_record/reflection.rb:183:in
build_association'
from /.rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.13/lib/active_record/associations/association.rb:233:inbuild_record' from /.rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.13/lib/active_record/associations/collection_association.rb:112:in
build'
from /.rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.13/lib/active_record/nested_attributes.rb:406:inblock in assign_nested_attributes_for_collection_association' from /.rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.13/lib/active_record/nested_attributes.rb:401:in
each'
from /.rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.13/lib/active_record/nested_attributes.rb:401:inassign_nested_attributes_for_collection_association' from /.rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.13/lib/active_record/nested_attributes.rb:289:in
bodies_attributes='
from /.rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.13/lib/active_record/attribute_assignment.rb:94:inblock in assign_attributes' from /.rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.13/lib/active_record/attribute_assignment.rb:93:in
each'
from /.rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.13/lib/active_record/attribute_assignment.rb:93:inassign_attributes' from /.rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.13/lib/active_record/base.rb:498:in
initialize'
from (irb):10:innew' from (irb):10 from /.rvm/gems/ruby-1.9.3-p392/gems/railties-3.2.13/lib/rails/commands/console.rb:47:in
start'
from /.rvm/gems/ruby-1.9.3-p392/gems/railties-3.2.13/lib/rails/commands/console.rb:8:instart' from /.rvm/gems/ruby-1.9.3-p392/gems/railties-3.2.13/lib/rails/commands.rb:41:in
<top (required)>'
from script/rails:6:in `require'
Hope this can be fixed, thanks for the awesome gem!
Have you already planned working on this or should I/we start a new PR ?
Looks like half of the methods doesn't need to be changed from version 4.2 to 5.0
OK = 4.2 == 5.0
module Associations ; class Association ; def creation_attributes
OK
class JoinAssociation < JoinPart ; def join_constraints
different
class BelongsToPolymorphicAssociation ; private ; def replace_keys
OK
class Preloader ; class Association ; def build_scope
differet
module ThroughAssociation ; private ; def through_scope
different
class AssociationScope
def self.get_bind_values
OK
def next_chain_scope
different
def last_chain_scope
different
module ThroughAssociation ; def construct_join_attributes
OK
class HasManyThroughAssociation ; def build_through_record
OK
class ThroughReflection ; def scope_chain
OK
Hello.
Firstly, I'd like to thank you for the work you've put into this Gem. It's helped me out on a large project and I'm super grateful that you were able to put into the time to maintain it over the years.
There is a PR #39 for adding Rails 6.0 support that is awaiting merging into master and I was wondering if that is on your roadmap in the near future?
Thank you again.
Paul.
Any update for Rails / ActiveRecord 4.2 ?
no time to respond, no discussion...
you're doing great open source!
keep koing asshole!
See:
Any plan to support Rails4?
Hey guys,
I discovered this gem today and integrated it into my Rails application. Everything was working swell until I came across this error:
ArgumentError: wrong number of arguments (1 for 0)
ruby-2.1.5/gems/agent-0.9.1/lib/agent/kernel/select.rb:4:in `select!'.
Upon diving deeper, I found that this gem was the culprit :x
gems/ruby-2.1.5/gems/agent-0.9.1/lib/agent/kernel/select.rb:4:in `select!'
gems/ruby-2.1.5/gems/store_base_sti_class-0.3.0/lib/store_base_sti_class_for_4_1.rb:128:in `build_scope'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader/has_one.rb:17:in `build_scope'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader/association.rb:28:in `scope'
I realized that it was breaking only in the case of adding a .includes
on the selector...
Business.first.staff
=> [ #<Staff id: 1, first_name: 'Jon', last_name: 'Doe'> ]
Business.includes(:staff).first.staff
ArgumentError: wrong number of arguments (1 for 0)
from /Users/dwm/.rvm/gems/ruby-2.1.5/gems/agent-0.9.1/lib/agent/kernel/select.rb:4:in `select!'
Does version 0.3.0 support Rails 4.1.9 or is 4.1.9 unsupported?
Here's the full BT if it is helpful :
gems/ruby-2.1.5/gems/agent-0.9.1/lib/agent/kernel/select.rb:4:in `select!'
gems/ruby-2.1.5/gems/store_base_sti_class-0.3.0/lib/store_base_sti_class_for_4_1.rb:128:in `build_scope'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader/has_one.rb:17:in `build_scope'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader/association.rb:28:in `scope'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader/association.rb:36:in `query_scope'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader/association.rb:32:in `records_for'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader/association.rb:118:in `block in load_slices'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader/association.rb:117:in `each'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader/association.rb:117:in `each_slice'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader/association.rb:117:in `each'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader/association.rb:117:in `flat_map'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader/association.rb:117:in `load_slices'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader/association.rb:91:in `associated_records_by_owner'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader/singular_association.rb:9:in `preload'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader/association.rb:20:in `run'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:137:in `block (2 levels) in preloaders_for_one'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:135:in `each'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:135:in `map'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:135:in `block in preloaders_for_one'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:134:in `each'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:134:in `flat_map'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:134:in `preloaders_for_one'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:106:in `preloaders_on'
gems/ruby-2.1.5/gems/bullet-4.14.0/lib/bullet/active_record41.rb:35:in `preloaders_on'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:94:in `block in preload'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:93:in `each'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:93:in `flat_map'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:93:in `preload'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader/through_association.rb:14:in `associated_records_by_owner'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader/singular_association.rb:9:in `preload'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader/association.rb:20:in `run'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:137:in `block (2 levels) in preloaders_for_one'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:135:in `each'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:135:in `map'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:135:in `block in preloaders_for_one'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:134:in `each'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:134:in `flat_map'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:134:in `preloaders_for_one'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:116:in `block in preloaders_for_hash'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:115:in `each'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:115:in `flat_map'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:115:in `preloaders_for_hash'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:104:in `preloaders_on'
gems/ruby-2.1.5/gems/bullet-4.14.0/lib/bullet/active_record41.rb:35:in `preloaders_on'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:94:in `block in preload'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:93:in `each'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:93:in `flat_map'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/associations/preloader.rb:93:in `preload'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/relation.rb:617:in `block in exec_queries'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/relation.rb:616:in `each'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/relation.rb:616:in `exec_queries'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/relation.rb:493:in `load'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/relation.rb:238:in `to_a'
gems/ruby-2.1.5/gems/bullet-4.14.0/lib/bullet/active_record41.rb:10:in `to_a'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/relation/finder_methods.rb:460:in `find_take'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/relation/finder_methods.rb:98:in `take'
gems/ruby-2.1.5/gems/activerecord-4.1.9/lib/active_record/relation/finder_methods.rb:81:in `find_by'
Given the following class definitions,
class Address
belongs_to :addressable, :polymorphic => true
end
class Person
has_many :addresses, :as => addressable
end
class Vendor < Person
end
and given the following code,
vendor = Vendor.create(...)
address = vendor.addresses.create(...)
p Address.where(addressable: address).to_sql
will output,
SELECT `addresses`.* FROM `addresses` WHERE `addresses`.`addressable` = 'Person' AND `addresses`.`addressable_id` = 1
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.