Forum: Ruby on Rails Simple caching

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
520c24bad2fa9b171d022e3600cd5e58?d=identicon&s=25 Noten Mark (Guest)
on 2006-12-27 15:12
I'm quite a newbie to Ruby and I need some help. I've got a database
table called agents that looks something like this:

create table agents {
  id mediumint(8) unsigned not null,
  surname varchar(60),
  forename varchar(60),
  manager_id mediumint(8) unsigned,
  primary key(id),
  constraint fk_manager(manager_id)
    references agents(id)
    on delete restrict
    on update restrict
}

This simple table represents a sales structrue. I've generated the model
and I have an Agent Ruby class and added associations has_many agents
and belongs_to agent. I've added also a method called full_name that
just concatenates :surname and :forename.

I would now like to have the generated list view besides the surname and
forename of each agent also show the name of the manager ( manager is an
agent where id = agent.manager_id). There are some agents that don't
have a manager aboven them.

I've added a method called manager_full_name to the Agent Ruby class to
avoid too much logic in the view. The code looks something like this:

def manager_full_name
  manager = self.agent
  manager_full_name = ''
  manager_full_name = manager.full_name unless manager == Nil
  manager_full_name
end

I use the <%= agent.manager_full_name => in my list view but it always
prints out nothing.

How can I print out the name of the manager in the view? Can I use
simple instance variable like @manager_full_name to cach the name of the
manager? I want to avoid an extra query for each time an agent is
printed out.

The ideal way is to set the @manager_full_name instance variable at
creation time (I doesn't go with the initialize method) and set a new
value when the agent is updated.

Another thing is how to display a structure (tree) of agents with each
agent on the right level. Something like this:

   A1
    |
A2 A7 A4
   |   | \
   A9  A5 A7

It will quickly get ugly in the view... :-(

Any suggestions are welkom!

Thans in advance,

Mark
86e084334c00a932a3675adbf769de67?d=identicon&s=25 Paul Corcoran (Guest)
on 2006-12-27 20:23
(Received via mailing list)
I think you will need to use acts_as_tree (or some other method like
nested_set?) rather than using a circular belongs_to in the same class.
Try this:

class Agent < ActiveRecord::Base
  acts_as_tree :foreign_key => "manager_id"

  def manager_full_name
  manager = self.parent
  manager_full_name = ''
  manager_full_name = manager.full_name unless manager == nil
  manager_full_name
  end

end

Note: the default foreign_key column to get the parent is parent_id but
we can override that since you called it manager_id. Also, self.agent
in your example becomes self.parent.

There were a couple of typos in your example that you are probably
aware of but here they are anyway: Nil should be lowercase nil and <%=
agent.manager_full_name => should be <%= @agent.manager_full_name %>.

To retrieve the agent AND the parent from the database with a single
query use the  :include parameter as follows: @agent = Agent.find(2),
:include => :parent). This will retrieve the agent row for id 2 along
with it's parent at the same time.

I don't have a good UI solution for displaying these in heirarchical
order. Maybe someone else has tried it.

-Paul
520c24bad2fa9b171d022e3600cd5e58?d=identicon&s=25 Mark Noten (mnoten)
on 2006-12-28 09:57
Thanks a lot Paul, your solution with the acts_as_tree works great. I've
found a also a nice article about it on
http://brianfox.wordpress.com/2006/09/08/parent-an...

This code is just enough to get the manager's name:

manager_full_name = ''
manager_full_name = manager.full_name unless manager

I've added the ':include => :parent' to the 'edit' and 'show' action in
the agents_controller. But I don't know how you can add it to the 'list'
action when you do a Agent.find(:all). How can you get a list of agents
and at the same time load the parent of each agent.

I think you would have to write a custom SQL select statement if you
want to avoid a query for getting the parent of each agent in the list.

Code for displaying a tree structure in the GUI with ruby must exist
somewhere. Let's hope I can find it.

Thanks,

Mark
86e084334c00a932a3675adbf769de67?d=identicon&s=25 Paul Corcoran (Guest)
on 2006-12-28 17:16
(Received via mailing list)
>But I don't know how you can add it to the 'list'
>action when you do a Agent.find(:all). How can you get a list of agents
>and at the same time load the parent of each agent.

Just do Agent.find(:all, :include => :parent).

-Paul
This topic is locked and can not be replied to.