This project is archived and is in readonly mode.
Model.has_many_through_association.find(id) returns a read-only record
-
Paul Rosania
Confirmed under Rails 3 RC2.
-
oleg dashevskii
I've added a test proving this bug.
-
Neeraj Singh
- Importance changed from to Low
This is not a bug. It is an undocumented feature. :-)
Look at following test cases which is already there in ActiveRecord.
def test_habtm_find_readonly dev = Developer.find(1) assert !dev.projects.empty? assert dev.projects.all?(&:readonly?) assert dev.projects.find(:all).all?(&:readonly?) assert dev.projects.readonly(true).all?(&:readonly?) end def test_has_many_find_readonly post = Post.find(1) assert !post.comments.empty? assert !post.comments.any?(&:readonly?) assert !post.comments.find(:all).any?(&:readonly?) assert post.comments.readonly(true).all?(&:readonly?) endAs you can see by default with habtm all the retrieved records are marked as readonly.
Although it is not there in the test but you can pass readonly(false) and you will get non readonly records.
Check this out
class Post < ActiveRecord::Base has_many :taggings has_many :tags, :through => :taggings def self.lab tmp = Post.first.tags.readonly(true).find(1).readonly? puts tmp #=> true end end class Post < ActiveRecord::Base has_many :taggings has_many :tags, :through => :taggings def self.lab tmp = Post.first.tags.readonly(false).find(1).readonly? puts tmp #=> false end end -
Neeraj Singh
I should have tested with habtm rather than has_many through. But the ActiveRecord test is with habtm.
-
Paul Rosania
Are there safety consequences to using #readonly(false) during retrieval?
Why is it defaulted to readonly in this case? Results retrieved through HMT have been readonly? #=> false for a long time (since first beta?). (I believe this has been the case since HMT was introduced.) Is readonly(true) necessary for some reason now?
-
Neeraj Singh
Good questions. And I do not have answer.
With final release of rails 3 so close I believe we should not change API much. I would try to dig deeper into this issue later.
-
Paul Rosania
Thanks for the quick reply! I took one more peek at the Rails source, and I actually think that the current behavior (readonly? #=> true) contradicts this test, introduced in Rails 1.15:
activerecord/test/cases/readonly_test.rb:69
def test_has_many_with_through_is_not_implicitly_marked_readonly assert people = Post.find(1).people assert !people.any?(&:readonly?) endSee commit http://github.com/rails/rails/commit/3f049b0b6b5a338786c3dfafb31edf...
I spent some time tracing execution yesterday, but I haven't been able to identify the change between RC and RC2 that causes the regression.
-
oleg dashevskii
Paul, this test is noop, since :people fixture isn't loaded and empty array passes the test. I've changed it (see the patch) and it still passes! So the problem is only with find(id) call, which returns a readonly record for some reason.
Returning back to my IRB session:
ree-1.8.7-2010.02 > Provider.first.dishes.find(1).readonly? => true ree-1.8.7-2010.02 > Provider.first.dishes.map(&:readonly?).uniq => [false]This is clearly a bug.
-
Paul Rosania
I just noticed the same thing. To clarify, readonly_test.rb currently specifies the following:
- Model.habtm.find(1).readonly? #=> true
- Model.has_many.find(1).readonly? #=> false
There is no test of has_many :through behavior, which has changed from readonly #=> false to readonly #=> true between RC and RC2.
This change is likely an unintended side-effect of changes to the Relation class since RC, but I have not been able to isolate it.
-
oleg dashevskii
- Title changed from Model.has_many_through_association.find(id) returns a read-only record to [PATCH] Model.has_many_through_association.find(id) returns a read-only record
This is a rather obscure bug. I'm glad to say I finally traced it down.
ActiveRecord::QueryMethods#build_selectwasn't resetting@implicit_readonlysince it was passed emptyselectsargument. The RC version was usingselects.present?check which returned true even for empty array. And theselectswere empty because of the finder options slicing.The fix is attached.
-
oleg dashevskii
- Tag changed from activerecord rails3, find_one, has_many_through_association, readonly to activerecord rails3, find_one, has_many_through_association, patch, readonly
-
Justin Smestad
Running into this bug as well. Quite annoying. +1 for this being fixed in 3.0.0 final.
-
Santiago Pastorino
- Milestone cleared.
- State changed from new to open
-
Jeff Kreeftmeijer
- Title changed from [PATCH] Model.has_many_through_association.find(id) returns a read-only record to Model.has_many_through_association.find(id) returns a read-only record
- Tag set to has_many_through, patch
Using the "patch" tag instead of prefixing the ticket title with "[PATCH]" to make sure patched tickets end up in the open patches bin. :)
-
Espen Antonsen
I assume this is not fixed in 3.0.1? Can reproduce on 3.0.1 in my project.
-
Jason King
Still exists in 3.0.3
-
Jason King
You can work around it declaratively too:
has_many :foos, :through => :bars, :readonly => false -
Jon Leighton
- Assigned user set to Aaron Patterson
Hi,
This patch didn't apply cleanly for me initially. I merged in the tests and ran them, and they passed on master and on 3-0-stable. I've attached an updated patch containing these tests which I think should be applied to guard against regressions.
I'm not sure whether the change that was proposed in
AssociationCollection#findshould still be applied, but if so presumably that's a different issue as these tests not pass. I've left it out for now.Thanks
-
Jon Leighton
- Milestone set to 3.1
Contrary to my earlier assertion, this is not fixed in 3-0-stable. It is, however, fixed in master.
I've looked into fixing it in 3-0-stable but my personal opinion is that it's too complicated and therefore not worth it. The root of the problem is that 3-0-stable generates strings for the
INNER JOINs it performs, which then causes the@implicit_readonlyflag to get set when building the Arel query. In master, the joins are built as Arel objects instead, so this flag is not set.I've also attached a new patch against master which cleans up the tests a little, and also fixes the third one (which was not actually testing what it said it was testing).
-
Jon Leighton
- State changed from open to resolved
-
Geoffrey Hichborn
Can you confirm that the suggested patch for 3.0-stable doesn't fix the issue/produces unexpected behavior?
-
Justin Smestad
This is marked as resolved however there is no commit referenced and the last comment from Jon said this could not be fixed till 3.1. Is this fixed or not?
-
Jason King
Actually, the last comment from Jon says that (a) it's already fixed in master (ie. 3.1), and (b) it's too complicated to fix it in 3.0
