This project is archived and is in readonly mode.
'type' field not filled when created from hierarchy
Reported by trevor | February 12th, 2010 @ 05:51 AM | in 3.x
this is a test case, so the has_many / belongs_to logic is off.
behavior i'm seeing is the 'type' field is automatically filled in with 'create', but not when called from a nested model. (in this example there's only one 'Second', but there should be two.)
% cat db/migrate/001_create_entries.rb
class CreateEntries < ActiveRecord::Migration
def self.up
create_table :entries do |t|
t.string :type
t.integer :parent_id
t.timestamps
end
end
end
% cat app/models/first.rb
class First < ActiveRecord::Base
set_table_name 'entries'
default_scope :conditions => {:type => 'First'}
has_many :seconds, :foreign_key => :parent_id
end
% cat app/models/second.rb
class Second < ActiveRecord::Base
set_table_name 'entries'
default_scope :conditions => {:type => 'Second'}
end
% rc
Loading development environment (Rails 3.0.0.beta)
irb(main):001:0> a = First.create
=> #<First id: 1, type: "First", parent_id: nil, created_at: "2010-02-12 05:40:34", updated_at: "2010-02-12 05:40:34">
irb(main):002:0> a.seconds
=> []
irb(main):003:0> a.seconds.create
=> #<Second id: 2, type: nil, parent_id: 1, created_at: "2010-02-12 05:40:44", updated_at: "2010-02-12 05:40:44">
irb(main):004:0> a.seconds
=> [#<Second id: 2, type: nil, parent_id: 1, created_at: "2010-02-12 05:40:44", updated_at: "2010-02-12 05:40:44">]
irb(main):005:0> b = Second.create
=> #<Second id: 3, type: "Second", parent_id: nil, created_at: "2010-02-12 05:40:59", updated_at: "2010-02-12 05:40:59">
irb(main):006:0> Second.all
=> [#<Second id: 3, type: "Second", parent_id: nil, created_at: "2010-02-12 05:40:59", updated_at: "2010-02-12 05:40:59">]
Comments and changes to this ticket
-
Ryan Bigg May 25th, 2010 @ 12:48 PM
- State changed from new to open
What happens if you set
self.inheritance_column
nil at the top of the Second model? type is a protected field. -
Neeraj Singh August 13th, 2010 @ 02:42 AM
- 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 August 15th, 2010 @ 04:07 PM
- 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 August 15th, 2010 @ 08:41 PM
Let's wait Trevor confirm if the patch really fixed the bug for him before applying it.
-
trevor August 16th, 2010 @ 05:11 PM
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 = nil
in the Second model has no effect. -
Neeraj Singh August 17th, 2010 @ 06:05 PM
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 August 17th, 2010 @ 06:25 PM
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 August 17th, 2010 @ 08:00 PM
@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 August 18th, 2010 @ 08:09 PM
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 lab
bug 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 August 19th, 2010 @ 11:12 AM
I just did rake db:drop; rake db:migrate and everything works for me.
-
trevor August 19th, 2010 @ 04:52 PM
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---' lab
running 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 August 19th, 2010 @ 05:11 PM
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 August 19th, 2010 @ 05:24 PM
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 August 19th, 2010 @ 05:26 PM
... 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 August 19th, 2010 @ 06:11 PM
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 August 19th, 2010 @ 06:30 PM
just tried that a few different ways and couldn't get it to take - weird bug.
-
José Valim August 19th, 2010 @ 06:31 PM
- 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 August 19th, 2010 @ 06:34 PM
- 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 August 19th, 2010 @ 06:35 PM
Without the patch post.comments.create will create the new comment record without the default scope applied for Comment.
-
trevor August 19th, 2010 @ 06:38 PM
+1 agreed - patch works and fixes issue. small edge case related bug with STI.
-
José Valim August 24th, 2010 @ 04:43 AM
- 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...
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>