I have the following 3 classes:
class User < ActiveRecord::Base
has_many(:project_roots)
end
class Project < ActiveRecord::Base
self.acts_as_tree(:order => “title”, :uniq=>true)
def user()
self.root.user()
end
end
class ProjectRoot < Project
self.belongs_to(:user)
def user()
read_attribute(:user)
end
end
and these 2 migrations:
class CreateProjects < ActiveRecord::Migration
def self.up
create_table :projects do |t|
t.column :type, :string # single-table inheritance
# common attributes
t.column :parent_id, :integer
t.column :title, :string
t.column :description, :text
# attributes for type=ProjectRoot
t.column :user_id, :integer
end
end
end
class CreateUsers < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.column :name, :string
t.column :password_code, :string
t.column :password_salt, :string
end
end
end
First I uncomment out ProjectRoot#user, and then do this in a console:
u1=User.find_first
p1=ProjectRoot.new(:title=>‘p1’, :description=>‘p1’)
u1.project_roots<<p1
p1.user
=> nil
I put the comments back in (and bring up a new console, and again run
the above) and now correctly get this:
p1.user
=> #<User:0x4807bdc …>
- Why is read_attribute not working?
Furthermore, (with the comments left in) I proceed to do:
p2=Project.new(:title=>‘p2’, :description=>‘p2’)
p1.children<<p2
p2.root
=> #<ProjectRoot:0x47f4ed8 @attributes={“title”=>“p1”, …>
p2.user
=> #<User:0x47f1f94 …>
- Why don’t I get into an infinite loop with Project#user? (Actually
this consideration was the very reason for implementing
ProjectRoot#user.)
All help greatly appreciated.
Um, are you trying to get the user name for the project?
Why are you specifying a belongs_to and a read_attribute? There is no
attribute called user in the projects table.
Also you’re using parenthesis around everything! You don’t need to do
this!
has_many(:project_roots) can be written as has_many :project_roots
def user() can be written as def user
self.root.user() can be written as self.root.user
The has_many and belongs_to looks like it’s working as it should be,
assuming you only want one user to have many projects.
if you want many users to have many projects use
has_and_belongs_to_many.
On Dec 18, 2007 10:56 AM, Paul D. [email protected] wrote:
self.root.user()
t.column :description, :text
t.column :name, :string
p1=ProjectRoot.new(:title=>‘p1’, :description=>‘p1’)
- Why is read_attribute not working?
- Why don’t I get into an infinite loop with Project#user? (Actually
this consideration was the very reason for implementing
ProjectRoot#user.)
All help greatly appreciated.
–
Ryan B.
Ok thanks. I missed the boat with the read_attribute, but the basic
idea still stands – to avoid the infinite loop. I still don’t
understand why it’s not a problem. As far as the parenthesis, I know
all about them and use them because I don’t like sugar. And thanks
for the tip with the has_and_belongs_to_many.
What infinite loop are you on about? Project already knows about its
user!
On Dec 18, 2007 11:30 AM, Paul D. [email protected] wrote:
self.root.user() can be written as self.root.user
class Project < ActiveRecord::Base
end
# common attributes
class CreateUsers < ActiveRecord::Migration
First I uncomment out ProjectRoot#user, and then do this in a console:
p1.user
p2.user
–
Ryan B.
ProjectRoot is a subclass of Project. Project implements user as
def user
self.root.user
end
ProjectRoot inherits this implementation. In ProjectRoot, self.root
returns self, as shown in this console snippet:
p1=ProjectRoot.new(:title=>‘p1’, :description=>‘p1’)
p1.root.equal?(p1)
=> true
It’s as if ProjectRoot had this method for user:
def user
self.user
end
This is what I would call an infinite loop!
-PD
Project is a tree structure, with a ProjectRoot as the tree root.
User only knows about ProjectRoots. A (regular) Project asks its root
for the user. I understand what you are writing, but would still like
an answer regarding the infinite loop. Thanks
I still don’t get what you’re trying to do.
Are you trying to get ProjectRoot and Project to both have access to the
user? Which one of these models is user linked to? If it’s linked to
ProjectRoot you can, in User do this:
class User < ActiveRecord::Base
has_many :projects, :through => “ProjectRoot”
end
On Dec 18, 2007 12:03 PM, Paul D. [email protected] wrote:
p1.root.equal?(p1)
-PD
Um, are you trying to get the user name for the project?
On Dec 18, 2007 10:56 AM, Paul D. [email protected]
def user()
t.column :title, :string
create_table :users do |t|
p1.user
p2.user
Ryan B.http://www.frozenplague.net-Hide quoted text -
–
Ryan B.http://www.frozenplague.net- Hide quoted text -
–
Ryan B.
Perhaps you’re looking for something like acts_as_tree?
On Dec 18, 2007 12:16 PM, Paul D. [email protected] wrote:
user? Which one of these models is user linked to? If it’s linked to
returns self, as shown in this console snippet:
This is what I would call an infinite loop!
Ok thanks. I missed the boat with the read_attribute, but the
Um, are you trying to get the user name for the project?
end
def user()
t.column :type, :string # single-table inheritance
end
I put the comments back in (and bring up a new console, and
ProjectRoot#user.)
–
Ryan B.http://www.frozenplague.net- Hide quoted text -
–
Ryan B.
Exactly. To quote from my original post:
class Project < ActiveRecord::Base
self.acts_as_tree(:order => “title”, :uniq=>true)
-PD
Paul D. wrote:
Project is a tree structure, with a ProjectRoot as the tree root.
User only knows about ProjectRoots. A (regular) Project asks its root
for the user. I understand what you are writing, but would still like
an answer regarding the infinite loop. Thanks
Because the user method is automatically generated by ActiveRecord::Base
and overrides yours ?
If I’m right calling user on a child Project should return nil with your
code. Assuming I’m right, you’d have to use a different name for your
user method or your user_id column or define your user method after
AR::B generates its methods. IIRC you can do it in after_initialize.
Lionel
Then why do you have something called a ProjectRoot? This is unneeded.
Acts
as tree should know which was the initial project by being able to climb
“up” the tree until it finds the root, i.e. the only thing along that
chain
without a parent id.
On Dec 18, 2007 12:18 PM, Paul D. [email protected] wrote:
for the user. I understand what you are writing, but would still like
class User < ActiveRecord::Base
end
def user
user!
know
There
has_many(:project_roots) can be written as has_many
has_many(:project_roots)
self.belongs_to(:user)
create_table :projects do |t|
end
end
=> nil
- Why is read_attribute not working?
–
Ryan B.http://www.frozenplague.net- Hide quoted text -
–
Ryan B.
Thanks, but I have my reasons…
-PD