Forum: Ruby on Rails aggregation/composed model attribute

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.
alien8 (Guest)
on 2005-12-06 21:24
(Received via mailing list)
First off, apologies about my previous empty post.

Also, apologies for the newbie nature of this post. I am new to rails
and I'm working on a simple relational database to be administered
and accessible to the public through rails. I have a question about
aggregation as outlined in the pragprog "agile web development" book,
around page 258 to 260. My example is nearly identical to the one
used in the book. I have basically followed the example there to the
letter, the only difference is that I want to aggregate fields from a
model called Author rather than Customer, and one of the field names
is different.

My question is simply this, once the Author model refers to the new
Name model, how can I access the new :name attribute of instances of
Author? I tried to do that in a view with the following code: <td><%=
author[:name] %></td> It doesn't return an error, just doesn't output
anything. The book shows how to created a new instance of Customer
with the aggregate Name object, but what about instances from a
database record? Shouldn't they have a :name attribute if they have
all the attributes that it's composed of?

The code I've used for Author and Name models is below. Thanks in
advance for any info on where I'm going wrong.

*** app/models/author.rb ***
class Author < ActiveRecord::Base

   has_and_belongs_to_many :books
   validates_presence_of :first_name, :last_name

   # composed_of declaration maps Author attributes to the Name model
object
   composed_of :name,
               :class_name => Name,
               :mapping =>
                 [ [ :first_name, :first ],
                   [ :other_name, :other],
                   [ :last_name, :last]
                 ]
end
***

*** app/models/name.rb ***
# Class defines the Name object, aggregation of attirbutes of Author
# object.
class Name
   attr_reader :first, :other, :last

   def initialize(first, other, last)
     @first = first
     @other = other
     @last = last
   end

   def to_s
     [ @first, @other, @last ].compact.join(" ")
   end
end
codyfauser (Guest)
on 2005-12-06 22:50
(Received via mailing list)
Use: <td><%= author.name  %></td> then check out page 203.



Cody

On 12/6/05, Alien8 Recordings <removed_email_address@domain.invalid> wrote:
> is different.
> The code I've used for Author and Name models is below. Thanks in
>    composed_of :name,
> # Class defines the Name object, aggregation of attirbutes of Author
>    def to_s
>      [ @first, @other, @last ].compact.join(" ")
>    end
> end
>
>
> _______________________________________________
> Rails mailing list
> removed_email_address@domain.invalid
> http://lists.rubyonrails.org/mailman/listinfo/rails
>


--
http://www.codyfauser.com
alien8 (Guest)
on 2005-12-07 00:08
(Received via mailing list)
Hey Cody,

Sorry, just one more question. I see that you can't use symbols to
access model attributes that are aggregated, but what does one do in
the case when one wants to pass them to a method that requires
symbols, such as:
      auto_complete_for :post, :title

Thanks,
Sean

On 6-Dec-05, at 3:47 PM, Cody F. wrote:

>> and I'm working on a simple relational database to be administered
>> Author? I tried to do that in a view with the following code: <td><%=
>> class Author < ActiveRecord::Base
>>                    [ :other_name, :other],
>>
>>
> _______________________________________________
> Rails mailing list
> removed_email_address@domain.invalid
> http://lists.rubyonrails.org/mailman/listinfo/rails
>
>

______________
ALIEN8 RECORDINGS
P.O. BOX 666, STATION R
MONTREAL, QC
CANADA, H2S 3L1

http://www.alien8recordings.com
codyfauser (Guest)
on 2005-12-07 01:17
(Received via mailing list)
Sean,

It all depends on what you're doing.  The reason auto_complete_for
doesn't work on the aggregate is because it builds the sql where
conditions based on the symbol you pass in.  Since there isn't a
'name' column in your table the query will fail.  Click the 'show
source' link on the rdocs for auto_complete_for for more details:
http://api.rubyonrails.com/classes/ActionControlle...

Depending on your circumstances you could still access the attributes
author.first_name author.last_name. Otherwise, in the case of
autocomplete you can check out Thomas F.' fantastic demos at
http://demo.script.aculo.us/, which show a customized autocomplete in
action.



Cody



On 12/6/05, Alien8 Recordings <removed_email_address@domain.invalid> wrote:
>
> >>
> >> My question is simply this, once the Author model refers to the new
> >>
> >>                :mapping =>
> >> class Name
> >>    end
> > --
> P.O. BOX 666, STATION R
> MONTREAL, QC
> CANADA, H2S 3L1
>
> http://www.alien8recordings.com
>
> _______________________________________________
> Rails mailing list
> removed_email_address@domain.invalid
> http://lists.rubyonrails.org/mailman/listinfo/rails
>


--
http://www.codyfauser.com
alien8 (Guest)
on 2005-12-10 05:04
(Received via mailing list)
Hey Cody,

Thanks for yet more help on this issue (I've been working on other
things in the last few days).

I was able to get a custom auto_complete for function working, but
now I am starting to wonder if creating an attribute by aggregation
was really the way to go. When I submit the search form that I am
using the auto_complete_for text field in I am calling a find() on
the author model with a conditional statement and rendering an
editing form with the resulting record. Since I have now learned that
apparently all finds on columns other than id require sql (the
conditional statements) I guess I'm in the same position that led me
to try the custom auto_complete_for function. So I guess now my
question is: do you know a way to do a conditional find on an active
record object, so that I can match to the aggregated Name attribute?
If not, I wonder if there is any way to get the auto_complete_for
text field to pass an id even while the author name is being displayed.

Thanks again,
Sean


On 6-Dec-05, at 6:15 PM, Cody F. wrote:

> Depending on your circumstances you could still access the attributes
>
>> Sean
>>>> First off, apologies about my previous empty post.
>>>> letter, the only difference is that I want to aggregate fields
>>>> author[:name] %></td> It doesn't return an error, just doesn't
>>>> class Author < ActiveRecord::Base
>>>>                  [ [ :first_name, :first ],
>>>> class Name
>>>>    end
>>> --
>> P.O. BOX 666, STATION R
>
>
> --
> http://www.codyfauser.com
>
>

______________
ALIEN8 RECORDINGS
P.O. BOX 666, STATION R
MONTREAL, QC
CANADA, H2S 3L1

http://www.alien8recordings.com
codyfauser (Guest)
on 2005-12-10 08:16
(Received via mailing list)
Sean,

For autocompleting names I usually cheat and create a full_name
attribute for the object.  Then I create a before_save callback that
creates the full name from the first and last name.  I am sacrificing
the extra storage space for convenience.  I find it is usually easier
to bend your ideals to match Rails than the other way around.

class Person < ActiveRecord::Base
  validates_presence_of :first_name, :last_name
  before_save :generate_full_name

  composed_of :name,
              :mapping => [ [ :first_name, :first], [ :last_name, :last
] ]

  def self.find_by_name(name)
    self.find_all_by_first_name_and_last_name(name.first, name.last)
  end

  private
    def generate_full_name
      self.full_name = self.first_name + " " + self.last_name
    end
end

class Name
  attr_reader :first, :last

  def initialize(first, last)
    @first, @last = first, last
  end

  def last_first
    "#@last, #@first"
  end
end

This way you can keep all of your methods that are specific to names,
like last_first, in the Name class and use them for display purposes,
but you can still conveniently autocomplete forms.  There is some
duplication, but I don't think it really matters in the long run.

There are also dynamically generated finders for your attributes.
These methods are automatically available for the model I've created
above (and more):

Person.find_by_first_name_and_last_name('Cody', 'Fauser')
Person.find_all_by_full_name('Cody F.')

And using the method defined above:
Person.find_by_name(Name.new('Cody', 'Fauser'))

Hope this helps.


Cody


On 12/9/05, Alien8 Recordings <removed_email_address@domain.invalid> wrote:
> editing form with the resulting record. Since I have now learned that
>
> > http://api.rubyonrails.com/classes/ActionController/Macros/
> > Cody
> >>       auto_complete_for :post, :title
> >>> Cody
> >>>> around page 258 to 260. My example is nearly identical to the one
> >>>> instances of
> >>>> advance for any info on where I'm going wrong.
> >>>>    composed_of :name,
> >>>> # Class defines the Name object, aggregation of attirbutes of
> >>>>
> >>>>
> >>
> >> removed_email_address@domain.invalid
> ALIEN8 RECORDINGS
> P.O. BOX 666, STATION R
> MONTREAL, QC
> CANADA, H2S 3L1
>
> http://www.alien8recordings.com
>
>


--
http://www.codyfauser.com
This topic is locked and can not be replied to.