to_xml

3 views
Skip to first unread message

Wouter

unread,
Jul 30, 2009, 11:26:25 AM7/30/09
to Ruby on Rails: Talk
Hey all,

I have some problems creating a rendered xml file

this is my source

def show_friends
@profile = Profile.find(user)
@list = @profile.send('friends').find(:all, :limit => 20, :order
=> 'RAND()')
@checkin = Checkin.find(:last, :conditions => {:profile_id =>
@list})
@place = @checkin.place
respond_to do |format|
format.html {render}
format.xml { render :xml => @list.to_xml(:dasherize =>
false)}
end
end

And this give as output

<profile>
<login>wouter</login>
<password>*</password>
...
</profile>

What i want to do now is include the @place object in my xml

so like this:

<profile>
<login>wouter</login>
<password>*</password>
<place>
<latitude>... </latitude>
..
</place>
</profile>

I know i can do :include => [:place] but this include all the places
from that person. I only want to get the last place where the user
checked in ( @checkin = Checkin.find(:last, :conditions =>
{:profile_id => @list})
@place = @checkin.place) . So i really have to include this, but
I have tried many things but nothing works.

How can i do this?

Thank you,

Wouter

cnk

unread,
Jul 30, 2009, 5:18:26 PM7/30/09
to Ruby on Rails: Talk
I think creating a builder file in your views directory will be the
easiest way to get exactly the xml output you want.

Josh

unread,
Jul 31, 2009, 1:13:50 AM7/31/09
to Ruby on Rails: Talk
I think the most efficient way would be to create a has_one in the
model with a unique name and use the conditions or order to get just
one entry. I just tested this on one of my apps and it worked pretty
well.
I assume here that friends are just other profiles and a profile has
many checkins?
so you probably have something similar in profile.rb
has_many :checkins
has_many :places, :through => :checkins
Add (I think anyways)
has_one :last_checkin, :class_name => "CheckIn", :order =>
'created_at'
has_one :last_place, :through => :last_checkin, :source => :place

And you can just do

@profile.send('friends').find(:all, :limit => 20, :order => 'RAND()',
include => :last_place) .to_xml(:include => :last_place)

* I put :last place in the finder to eager load, and again in the
to_xml so that is is included in the xml.

Another way which doesn't require the model modified or a builder and
is pretty ineffiecent for sql queries is

@items = @profile.send('friends').collect do |f|
h = f.attributes
h['place'] = f.checkins.last.place.attributes
h
end
@items.to_xml

Let me know if you still have problems and include the models.
-Josh

Wouter

unread,
Jul 31, 2009, 3:06:06 PM7/31/09
to Ruby on Rails: Talk
Hey Josh,

Thank you for your answer. I have implemented this in my model and
controller and it works half.
I will try to explain what the problem is.

This is my code from profile.rb

has_many :place
has_many :checkin
has_one :last_checkin, :class_name =>"Checkin", :order =>
"created_at desc"
has_one :last_place, :through => :last_checkin, :source => :place

so i get the last_checkin from my database sorted by latest,
last_place is then the place source from my last_checkin.
when i get the to_xml and have as include :last_checkin i see the
latest checkin

<last_checkin>
<created_at type="datetime">2009-07-31T19:00:49Z</created_at>
<device nil="true"/>
<id type="integer">100</id>
<places_id type="integer">59</places_id>
<profile_id type="integer">3</profile_id>
<status/>
</last_checkin>

my places_id is here 59 so i want to get the source of this place. But
now when i do :last_place i get this

<last_place>
<address nil="true"/>
<category nil="true"/>
<city>Namur</city>
<country>BE</country>
<created_at type="datetime">2009-07-31T18:43:50Z</created_at>
<id type="integer">57</id>
<latitude type="float">50.4641</latitude>
<longitude type="float">4.86043</longitude>
<name>Namen</name>
<updated_at type="datetime">2009-07-31T18:59:58Z</updated_at>
<zip type="integer" nil="true"/>
</last_place>

The id of place here is 57.

How does this comes and what am i doing wrong?

Thank you for your help!

Wouter

On Jul 31, 7:13 am, Josh <joshbwh...@gmail.com> wrote:
> I think the most efficient way would be to create a has_one in the
> model with a unique name and use the conditions or order to get just
> one entry. I just tested this on one of my apps and it worked pretty
> well.
> I assume here that friends are just other profiles and a profile has
> many checkins?
> so you probably have something similar in profile.rb
> has_many :checkins
> has_many :places, :through => :checkins
> Add (I think anyways)
> has_one :last_checkin, :class_name => "CheckIn", :order =>
> 'created_at'
> has_one :last_place, :through => :last_checkin, :source => :place
>
> And you can just do
>
> @profile.send('friends').find(:all, :limit => 20, :order => 'RAND()',
> include => :last_place) .to_xml(:include => :last_place)
>
> * I put :last place in the finder to eager load, and again in theto_xmlso that is is included in the xml.

Josh

unread,
Jul 31, 2009, 6:44:20 PM7/31/09
to Ruby on Rails: Talk
I took a look at my own code where I test implemented this and
realized I have the same problem.

After watching SQL in the log and playing around in script/console I
realized this was happening

If I type user.last_checkin.last_place I was getting the correct place
if I typed user.last_place it wasn't sorting by created_at anymore in
the query.
The same thing is happening in the to_xml...

This feels a little dirty to me, but it seems to work fine. Just
change the line in your model describing last_place to include the
ordered at on checkin table.

has_one :last_place, :through => :last_checkin, :source
=> :place, :order => 'checkin.created_at desc'

and you should see the correct 'last_place'

Let me know if this worked for you.

Wouter

unread,
Aug 13, 2009, 12:58:28 PM8/13/09
to Ruby on Rails: Talk
Hey,

Thank you so much!

It worked

SOrry for late answer but forgot to answer!

THANK YOU!
Reply all
Reply to author
Forward
0 new messages