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
Active Record: if an AR class is duplicated, records can be returned with incorrect class #7236
Comments
I don't mean to toot my own horn too much, but this is exactly what presenters/view models were created for: Draper, for example. |
|
@steveklabnik Is it me, or the link is broken? |
|
I'm an idiot and can't write markdown, apparently. Fixed! |
|
@steveklabnik, but the current behavior of AR, doesn't it look weird? |
|
Honestly, this is so far outside of a usual use-case that I have no idea if ActiveRecord's behavior is weird or not. I would personally not let this code pass a code review, so I have no idea what the proper semantics are in this case. |
|
@steveklabnik kinda off topic: Draper is nice for presenting models, but do you know of a lib that complements it by supporting roundtripping the presented data in a form? |
|
Oh, and User = ::User.dup
class User
endand class User < ::User
endare not even equivalent anyway. In one, you're |
|
@MSch you are correct, it is very off topic, but that isn't part of the presenter pattern, so it's outside of Draper's scope. What you want is an Further questions about this can be emailed to me, let's not derail this Issue. |
|
@steveklabnik, this is exactly why i wanted to use the first and not the second. But after thinking i while, the second might do for me. This is not important. I was reporting the issue because the behavior looked weird to me, because i thought that a duplication should not break any class, ActiveRecord or not. (Or it should break it in some predictable way.) |
|
The reason the class User < ActiveRecord::Base
def self.initialize_copy(other)
@relation = nil
@arel_table = nil
@arel_engine = nil
end
endThere may be other variables that need resetting, but this seems to work on first glance. @jonleighton do we want to support this properly by adding an |
|
@pixeltrix, i have just tried this with my script above, it didn't help. |
|
Rails probably does a number of things on class instantiation that are not being duplicated by |
|
I think the problem might be with metaclass (with class methods). Maybe it was a bad idea to experiment with this. If you do not see anything unusual, this issue can be closed, i think. |
|
Yeah, I don't think we should support this in Active Record. It seems quite an avant-garde technique and I don't want the maintenance burden. |
|
@alexeymuranov hmm, that worked in the rails console - gem 'activerecord', '3.2.7'
require 'active_record'
# Print out what version we're running
puts "Active Record #{ActiveRecord::VERSION::STRING}"
# ActiveRecord::Base.logger = Logger.new(STDOUT)
# Connect to an in-memory sqlite3 database (more on this in a moment)
ActiveRecord::Base.establish_connection( :adapter => 'sqlite3',
:database => ':memory:' )
# Create the minimal database schema necessary to reproduce the bug
ActiveRecord::Schema.define do
create_table "users", :force => true do |t|
end
end
# Create the minimal set of models to reproduce the bug
class User < ActiveRecord::Base
def self.dup
copy = super
copy.reset_class_variables
copy
end
def self.reset_class_variables
@arel_table = nil
@arel_engine = nil
@relation = nil
end
end
# Create some test data
User.create # XXX: this line is important
module M
User = ::User.dup
end
# Create some test data
User.create
# Reproduce the actual bug!
p M::User.first.class |
|
@pixeltrix, thanks for the explanation, it works. I will also think about Draper. |
Here is a strange issue with duplicating an AR class. The actual situation is more or less the following: i extend my models to be more friendly, like to know which fields to show and how to sort their records. These extensions are different in different controllers. To not worry about possible violations of Open/closed principle, i've decided to duplicate the model classes instead of inheriting from them, something like:
instead of
Then i started getting an error, apparently caused by a wrong model class being used, which depended on the order in which i visited pages of my application!
Here is a script to reproduce. I do not know if this should be considered a bug, but to me this behavior is strange:
Commenting or uncommenting the line marked with XXX changes the class of the record returned. I think it has to always be
M::User.Update: Same with
cloneinstead ofdup.The text was updated successfully, but these errors were encountered: