This project is archived and is in readonly mode.
'type' field not filled when created from hierarchy
-
Ryan Bigg
- State changed from new to open
What happens if you set
self.inheritance_columnnil at the top of the Second model? type is a protected field. -
Neeraj Singh
- Assigned user set to Neeraj Singh
- Tag set to rails 3, activerecord
- Importance changed from to Low
@trevor can you check if the attached patch fixes your problem.
-
Neeraj Singh
- Milestone set to 3.x
- Assigned user changed from Neeraj Singh to José Valim
- Tag changed from rails 3, activerecord to rails 3, activerecord, patch
I discussed this ticket briefly with Mr. Valim. Assigning it to him.
-
José Valim
Let's wait Trevor confirm if the patch really fixed the bug for him before applying it.
-
trevor
applied the patch, but still seeing the type being set to 'nil'.
irb(main):003:0> a.seconds.create => #<Second id: 2, type: nil, parent_id: 1, created_at: "2010-08-16 16:02:32", updated_at: "2010-08-16 16:02:32"> irb(main):004:0> a.seconds => [#<Second id: 2, type: nil, parent_id: 1, created_at: "2010-08-16 16:02:32", updated_at: "2010-08-16 16:02:32">]per Ryan - setting
self.inheritance_column = nilin the Second model has no effect. -
Neeraj Singh
Checked again and works for me.
Here is what I did
- checkout rails master
- applied patch
- execute First.lab
class CreateEntries < ActiveRecord::Migration def self.up create_table :entries do |t| t.string :type t.integer :parent_id t.timestamps end end end class Second < ActiveRecord::Base set_table_name 'entries' default_scope :conditions => {:type => 'Second'} end class First < ActiveRecord::Base set_table_name 'entries' default_scope :conditions => {:type => 'First'} has_many :seconds, :foreign_key => :parent_id def self.lab a = First.create puts a.inspect b = Second.create puts b.inspect b1 = a.seconds.create puts b1.inspect end end $ rails runner First.lab #<First id: 19, type: "First", parent_id: nil, created_at: "2010-08-17 16:55:03", updated_at: "2010-08-17 16:55:03"> #<Second id: 20, type: "Second", parent_id: nil, created_at: "2010-08-17 16:55:03", updated_at: "2010-08-17 16:55:03"> #<Second id: 21, type: "Second", parent_id: 19, created_at: "2010-08-17 16:55:03", updated_at: "2010-08-17 16:55:03"> -
trevor
this is interesting. note that i monkey-patched RC, this is the behavior that i'm seeing - please see if you can reproduce. it works correctly as soon as there's a Second type existing in the database, but not before.
% rake db:drop; rake db:migrate % rc Loading development environment (Rails 3.0.0.rc) irb(main):001:0> a = First.create => #<First id: 1, type: "First", parent_id: nil, created_at: "2010-08-17 17:19:31", updated_at: "2010-08-17 17:19:31"> irb(main):002:0> a.seconds.create => #<Second id: 2, type: nil, parent_id: 1, created_at: "2010-08-17 17:19:36", updated_at: "2010-08-17 17:19:36"> irb(main):003:0> Second.create => #<Second id: 3, type: "Second", parent_id: nil, created_at: "2010-08-17 17:19:45", updated_at: "2010-08-17 17:19:45"> irb(main):004:0> a.seconds.create => #<Second id: 4, type: "Second", parent_id: 1, created_at: "2010-08-17 17:19:59", updated_at: "2010-08-17 17:19:59"> irb(main):005:0> a.seconds => [#<Second id: 4, type: "Second", parent_id: 1, created_at: "2010-08-17 17:19:59", updated_at: "2010-08-17 17:19:59">, #<Second id: 2, type: nil, parent_id: 1, created_at: "2010-08-17 17:19:36", updated_at: "2010-08-17 17:19:36">] irb(main):006:0> exit % rc Loading development environment (Rails 3.0.0.rc) irb(main):001:0> a = First.create => #<First id: 5, type: "First", parent_id: nil, created_at: "2010-08-17 17:20:23", updated_at: "2010-08-17 17:20:23"> irb(main):002:0> a.seconds.create => #<Second id: 6, type: "Second", parent_id: 5, created_at: "2010-08-17 17:20:29", updated_at: "2010-08-17 17:20:29"> irb(main):003:0> -
Neeraj Singh
@Trevor Will it be possible for you to try the patch on rails edge instead of your monkey-patched version of RC. A lot has changed since RC.
-
trevor
trying patch with edge now, still seeing issue, try switching b1 with b in your example on a clean database.
## First-bug.lab class Second < ActiveRecord::Base set_table_name 'entries' default_scope :conditions => {:type => 'Second'} end class First < ActiveRecord::Base set_table_name 'entries' default_scope :conditions => {:type => 'First'} has_many :seconds, :foreign_key => :parent_id end def lab a = First.create puts a.inspect b1 = a.seconds.create puts b1.inspect b = Second.create puts b.inspect end labbug apparent when database is fresh, goes away when a 'Second' type exists -
% rake db:drop; rake db:migrate % rails runner First-bug.lab #<First id: 1, type: "First", parent_id: nil, created_at: "2010-08-18 19:01:11", updated_at: "2010-08-18 19:01:11"> #<Second id: 2, type: nil, parent_id: 1, created_at: "2010-08-18 19:01:11", updated_at: "2010-08-18 19:01:11"> #<Second id: 3, type: "Second", parent_id: nil, created_at: "2010-08-18 19:01:11", updated_at: "2010-08-18 19:01:11"> % rails runner First-bug.lab #<First id: 4, type: "First", parent_id: nil, created_at: "2010-08-18 19:01:25", updated_at: "2010-08-18 19:01:25"> #<Second id: 5, type: "Second", parent_id: 4, created_at: "2010-08-18 19:01:25", updated_at: "2010-08-18 19:01:25"> #<Second id: 6, type: "Second", parent_id: nil, created_at: "2010-08-18 19:01:25", updated_at: "2010-08-18 19:01:25"> % rake db:drop; rake db:migrate % rails runner First-bug.lab #<First id: 1, type: "First", parent_id: nil, created_at: "2010-08-18 19:03:17", updated_at: "2010-08-18 19:03:17"> #<Second id: 2, type: nil, parent_id: 1, created_at: "2010-08-18 19:03:17", updated_at: "2010-08-18 19:03:17"> #<Second id: 3, type: "Second", parent_id: nil, created_at: "2010-08-18 19:03:17", updated_at: "2010-08-18 19:03:17"> -
Neeraj Singh
I just did rake db:drop; rake db:migrate and everything works for me.
-
trevor
did you switch the creation order as well?
here's how i'm reproducing the issue, with CreateEntries as the migration. the issue is apparent with B.lab
### A.lab class Second < ActiveRecord::Base set_table_name 'entries' default_scope :conditions => {:type => 'Second'} end class First < ActiveRecord::Base set_table_name 'entries' default_scope :conditions => {:type => 'First'} has_many :seconds, :foreign_key => :parent_id end def lab a = First.create puts a.inspect b = Second.create puts b.inspect child = a.seconds.create puts child.inspect end lab puts '---again---' lab### B.lab class Second < ActiveRecord::Base set_table_name 'entries' default_scope :conditions => {:type => 'Second'} end class First < ActiveRecord::Base set_table_name 'entries' default_scope :conditions => {:type => 'First'} has_many :seconds, :foreign_key => :parent_id end def lab a = First.create puts a.inspect child = a.seconds.create puts child.inspect b = Second.create puts b.inspect end lab puts '---again---' labrunning with edge and patch
B.lab demonstrates if a child is created before a database entry of that child's type has yet to exist, it's type is set to nil.
% rake db:drop; rake db:migrate; rails runner A.lab #<First id: 1, type: "First", parent_id: nil, created_at: "2010-08-19 15:30:47", updated_at: "2010-08-19 15:30:47"> #<Second id: 2, type: "Second", parent_id: nil, created_at: "2010-08-19 15:30:47", updated_at: "2010-08-19 15:30:47"> #<Second id: 3, type: "Second", parent_id: 1, created_at: "2010-08-19 15:30:47", updated_at: "2010-08-19 15:30:47"> ---again--- #<First id: 4, type: "First", parent_id: nil, created_at: "2010-08-19 15:30:47", updated_at: "2010-08-19 15:30:47"> #<Second id: 5, type: "Second", parent_id: nil, created_at: "2010-08-19 15:30:47", updated_at: "2010-08-19 15:30:47"> #<Second id: 6, type: "Second", parent_id: 4, created_at: "2010-08-19 15:30:47", updated_at: "2010-08-19 15:30:47">% rake db:drop; rake db:migrate; rails runner B.lab #<First id: 1, type: "First", parent_id: nil, created_at: "2010-08-19 15:31:49", updated_at: "2010-08-19 15:31:49"> #<Second id: 2, type: nil, parent_id: 1, created_at: "2010-08-19 15:31:49", updated_at: "2010-08-19 15:31:49"> #<Second id: 3, type: "Second", parent_id: nil, created_at: "2010-08-19 15:31:49", updated_at: "2010-08-19 15:31:49"> ---again--- #<First id: 4, type: "First", parent_id: nil, created_at: "2010-08-19 15:31:49", updated_at: "2010-08-19 15:31:49"> #<Second id: 5, type: "Second", parent_id: 4, created_at: "2010-08-19 15:31:49", updated_at: "2010-08-19 15:31:49"> #<Second id: 6, type: "Second", parent_id: nil, created_at: "2010-08-19 15:31:49", updated_at: "2010-08-19 15:31:49">running unpatched 3.0RC
comparison to show what the patch has fixed.
% rake db:drop; rake db:migrate; rails runner A.lab #<First id: 1, type: "First", parent_id: nil, created_at: "2010-08-19 15:38:37", updated_at: "2010-08-19 15:38:37"> #<Second id: 2, type: "Second", parent_id: nil, created_at: "2010-08-19 15:38:37", updated_at: "2010-08-19 15:38:37"> #<Second id: 3, type: nil, parent_id: 1, created_at: "2010-08-19 15:38:37", updated_at: "2010-08-19 15:38:37"> ---again--- #<First id: 4, type: "First", parent_id: nil, created_at: "2010-08-19 15:38:37", updated_at: "2010-08-19 15:38:37"> #<Second id: 5, type: "Second", parent_id: nil, created_at: "2010-08-19 15:38:37", updated_at: "2010-08-19 15:38:37"> #<Second id: 6, type: nil, parent_id: 4, created_at: "2010-08-19 15:38:37", updated_at: "2010-08-19 15:38:37">% rake db:drop; rake db:migrate; rails runner B.lab #<First id: 1, type: "First", parent_id: nil, created_at: "2010-08-19 15:41:41", updated_at: "2010-08-19 15:41:41"> #<Second id: 2, type: nil, parent_id: 1, created_at: "2010-08-19 15:41:41", updated_at: "2010-08-19 15:41:41"> #<Second id: 3, type: "Second", parent_id: nil, created_at: "2010-08-19 15:41:41", updated_at: "2010-08-19 15:41:41"> ---again--- #<First id: 4, type: "First", parent_id: nil, created_at: "2010-08-19 15:41:41", updated_at: "2010-08-19 15:41:41"> #<Second id: 5, type: nil, parent_id: 4, created_at: "2010-08-19 15:41:41", updated_at: "2010-08-19 15:41:41"> #<Second id: 6, type: "Second", parent_id: nil, created_at: "2010-08-19 15:41:41", updated_at: "2010-08-19 15:41:41">if B.lab works fine for you on a clean database, then it may be specific to my system. it'd be good if we could reproduce it in the tests so it may be noticed by others.
% ruby -v ruby 1.9.2p0 (2010-08-18 revision 29036) [x86_64-darwin10.4.0] % sqlite3 --version 3.7.0.1 % gem list sqlite3 *** LOCAL GEMS *** sqlite3-ruby (1.3.1) -
Neeraj Singh
I am able to reproduce it. Thanks for your patience.
The reason why in B.lab you are getting 'type' as nil is class 'Second' is not loaded.
Everything works if class Second is loaded.
It is a known issue and it is documented. I tried to look for the documentation but am not able to find it here. Will add the link later when I find it.
Once again for Rails to work properly if STI is being used then all the STI classes should be pre loaded. This is an issue in development mode only. It will never happen in production.
Do notice that without the patch if you have class 'Second' loaded then alos I was getting nil.
-
trevor
okay, i'm good then. thanks for the patch and all your effort!
out of curiosity, how could i pre load the class in development?
for example i would have thought doing something like Second.new would take care of it -
def lab a = First.create puts a.inspect x = Second.new puts x child = a.seconds.create puts child.inspect b = Second.create puts b.inspect end#<First id: 1, type: "First", parent_id: nil, created_at: "2010-08-19 16:21:49", updated_at: "2010-08-19 16:21:49"> #<Second:0x000001025f8428> #<Second id: 2, type: nil, parent_id: 1, created_at: "2010-08-19 16:21:49", updated_at: "2010-08-19 16:21:49"> #<Second id: 3, type: "Second", parent_id: nil, created_at: "2010-08-19 16:21:49", updated_at: "2010-08-19 16:21:49"> ---again--- #<First id: 4, type: "First", parent_id: nil, created_at: "2010-08-19 16:21:49", updated_at: "2010-08-19 16:21:49"> #<Second:0x00000102570050> #<Second id: 5, type: "Second", parent_id: 4, created_at: "2010-08-19 16:21:49", updated_at: "2010-08-19 16:21:49"> #<Second id: 6, type: "Second", parent_id: nil, created_at: "2010-08-19 16:21:49", updated_at: "2010-08-19 16:21:49"> -
trevor
... and i meant that as -
#<First id: 1, type: "First", parent_id: nil, created_at: "2010-08-19 16:24:48", updated_at: "2010-08-19 16:24:48"> #<Second id: nil, type: "Second", parent_id: nil, created_at: nil, updated_at: nil> #<Second id: 2, type: nil, parent_id: 1, created_at: "2010-08-19 16:24:48", updated_at: "2010-08-19 16:24:48"> #<Second id: 3, type: "Second", parent_id: nil, created_at: "2010-08-19 16:24:48", updated_at: "2010-08-19 16:24:48"> ---again--- #<First id: 4, type: "First", parent_id: nil, created_at: "2010-08-19 16:24:48", updated_at: "2010-08-19 16:24:48"> #<Second id: nil, type: "Second", parent_id: nil, created_at: nil, updated_at: nil> #<Second id: 5, type: "Second", parent_id: 4, created_at: "2010-08-19 16:24:48", updated_at: "2010-08-19 16:24:48"> #<Second id: 6, type: "Second", parent_id: nil, created_at: "2010-08-19 16:24:48", updated_at: "2010-08-19 16:24:48"> -
Neeraj Singh
This is case where First and Second use 'type' but they are not subclass of any other model. For this case I would have just do
Class First
Second #loading Second for STI purpose
endclass Second
First #loading First for STI purpose
endIf they were subclases of another model called say 'Ranking' Then you could have used Ranking.descendants.each {|r| r }
-
trevor
just tried that a few different ways and couldn't get it to take - weird bug.
-
José Valim
- State changed from open to invalid
Confirm. In order for STI to work, all clases should be loaded before hand and I believe this is properly documented.
-
Neeraj Singh
- State changed from invalid to open
Setting the status to open.
The patch is still valid and the patch works for Trevor. It was not working only when he was not loading Second before hand.
:-)
-
Neeraj Singh
Without the patch post.comments.create will create the new comment record without the default scope applied for Comment.
-
trevor
+1 agreed - patch works and fixes issue. small edge case related bug with STI.
-
trevor
can this patch be added to 3.0 final?
-
José Valim
- State changed from open to committed
It was already applied. A typo in the commit message did not allow it to be reported back it here:
http://github.com/rails/rails/commit/2e455429427a4078d2888cc39305f9...
