Rendering User attributes in XML

Let’s say an app has a User, and a User has many friends. Also, let’s
say the app authentication was built on the restful_authentication
plugin, and we have email and password in the Users table. The friends
controller index might look like this;

GET /users/1/friends

GET /users/1/friends.xml

def index
@users = @user.friends

respond_to do |format|
format.html
format.xml { render :xml => @friends }
end
end

If the app needs to show all of a users friends in the XML output, what
is the best practice for handling the User model attributes that are
formatted in XML whilst not rendering sensitive attributes like email
and password? Does the app need a custom XML template for this? Or is
there a convenient way to not show the account credentials of the User
model when we’re shoving them in to the XML output?

Neil C. wrote:

Let’s say an app has a User, and a User has many friends. Also, let’s
say the app authentication was built on the restful_authentication
plugin, and we have email and password in the Users table. The friends
controller index might look like this;

GET /users/1/friends

GET /users/1/friends.xml

def index
@users = @user.friends

respond_to do |format|
format.html
format.xml { render :xml => @friends }
end
end

If the app needs to show all of a users friends in the XML output, what
is the best practice for handling the User model attributes that are
formatted in XML whilst not rendering sensitive attributes like email
and password? Does the app need a custom XML template for this? Or is
there a convenient way to not show the account credentials of the User
model when we’re shoving them in to the XML output?

No thoughts on this one? It sounds like something that any app with RA
based authentication & user record XML outputs would encounter. Someone
I’ve been working with suggested I take a look at this;

http://code.google.com/p/custom-xml-serialization/wiki/Overview

But seeings as there’s been no updates since last year, I was thinking
that maybe there’s something in Rails which I just don’t know about.

On Aug 30, 10:36 am, Neil C. [email protected]
wrote:

there a convenient way to not show the account credentials of the User
model when we’re shoving them in to the XML output?

No thoughts on this one? It sounds like something that any app with RA
based authentication & user record XML outputs would encounter. Someone
I’ve been working with suggested I take a look at this;

the to_xml method takes a bunch of options, including :only
and :except which allow you to exclude attributes.

Fred

Frederick C. wrote:

On Aug 30, 10:36�am, Neil C. [email protected]
wrote:

there a convenient way to not show the account credentials of the User
model when we’re shoving them in to the XML output?

No thoughts on this one? It sounds like something that any app with RA
based authentication & user record XML outputs would encounter. Someone
I’ve been working with suggested I take a look at this;

the to_xml method takes a bunch of options, including :only
and :except which allow you to exclude attributes.

Fred

Thanks Fred. I’ve come across the to_xml before, I just can’t work out
how to use it in conjunction with the format.xml helper;

respond_to do |format|
  format.html # index.html.erb
  format.xml  { @users.to_xml :except => [:email] }
end

(That tells me I need a template)

respond_to do |format|
  format.html # index.html.erb
  format.xml  { render :xml => @users.to_xml, :except => :email }
end

(And so does that)

By the looks of it, it would be cleaner to specify which attributes (the
ones we don’t want to show) in the User.rb. Does Rails have this built
in?

Frederick C. wrote:

On Aug 30, 1:13�pm, Neil C. [email protected]
wrote:

� � � format.xml �{ @users.to_xml :except => [:email] }
� � end

(That tells me I need a template)

� � respond_to do |format|
� � � format.html # index.html.erb
� � � format.xml �{ render :xml => @users.to_xml, :except => :email }
� � end

nearly - render :xml => @users.to_xml(:except => :email) should do it.

(And so does that)

By the looks of it, it would be cleaner to specify which attributes (the
ones we don’t want to show) in the User.rb. Does Rails have this built
in?

I imagine you could change the defaults by overriding to_xml in your
model. It probably wouldn’t be too hard to write this so that you
could do

class User < ActiveRecord::Base
exclude_from_xml :email, :password
end

Fred

Thanks Fred, the first method works a treat but, I just realised I have
15 attributes I need to hide away. My format.xml helper looks like
Pinocchios nose.

The model would be the way to go, and the API suggests it is easy to do;
http://docs.huihoo.com/api/ruby-on-rails/classes/ActiveRecord/XmlSerialization.html

…I just can’t work out how to simply exclude certain attributes; I
haven’t touched AR internals before so nothing within the def to_xml
makes any sense. Not that that is stopping me from allowing myself 10
minutes of trial & error though!

You could make an array

exclusions = [:email, :some_attr, :other_attr, …]

and use it instead of specifying all the exclusions inline

format.xml { render :xml => @users.to_xml, :except => exclusions }

since the docs indicate that you can use an array as the value for
:except.

Regards,
Craig

On Aug 30, 1:13 pm, Neil C. [email protected]
wrote:

  format.xml  { @users.to_xml :except => [:email] }
end

(That tells me I need a template)

respond_to do |format|
  format.html # index.html.erb
  format.xml  { render :xml => @users.to_xml, :except => :email }
end

nearly - render :xml => @users.to_xml(:except => :email) should do it.

(And so does that)

By the looks of it, it would be cleaner to specify which attributes (the
ones we don’t want to show) in the User.rb. Does Rails have this built
in?

I imagine you could change the defaults by overriding to_xml in your
model. It probably wouldn’t be too hard to write this so that you
could do

class User < ActiveRecord::Base
exclude_from_xml :email, :password
end

Fred

Craig D. wrote:

You could make an array

exclusions = [:email, :some_attr, :other_attr, …]

and use it instead of specifying all the exclusions inline

format.xml { render :xml => @users.to_xml, :except => exclusions }

since the docs indicate that you can use an array as the value for
:except.

Regards,
Craig

Thanks Craig. Are you saying (?);

def to_xml(options = {})
exclusions = [:email, :some_attr, :other_attr, …]
end

And in my controller;

format.xml { render :xml => @users.to_xml, :except => exclusions }

Or is it simpler than that?

Craig D. wrote:

Or is it simpler than that?
I’m suggesting

respond_to do |format|

format.xml do
exclusions = [ … ]
render :xml => @users.to_xml, :except => exclusions
end
end

simply as another way to accomplish what you want while striving for
something that may be more readable than specifying all of the
exclusions
inline.

Regards,
Craig

Thanks again, I was hoping I could specify the exclusions in the
User.rb. Is there any reason I couldn’t do that? There’s 5 or 6
controllers in which I’ll need the exclusions.

Or is it simpler than that?
I’m suggesting

respond_to do |format|

format.xml do
exclusions = [ … ]
render :xml => @users.to_xml, :except => exclusions
end
end

simply as another way to accomplish what you want while striving for
something that may be more readable than specifying all of the
exclusions
inline.

Regards,
Craig

By the way, this page was the inspiration for my last reply:

http://ryandaigle.com/articles/2007/4/13/what-s-new-in-edge-rails-a-more-flexible-to_xml

On Sat, Aug 30, 2008 at 11:42 AM, Craig D.

On Sat, Aug 30, 2008 at 10:47 AM, Neil C. <
[email protected]> wrote:

Thanks again, I was hoping I could specify the exclusions in the
User.rb. Is there any reason I couldn’t do that? There’s 5 or 6
controllers in which I’ll need the exclusions.

You could override to_xml like this if you’ll need the custom XML
everywhere:

class User < ActiveRecord::Base

you can choose a better name than ar_to_xml, of course

alias_method :ar_to_xml, :to_xml
def to_xml(options = {}, &blk)
# update this list with the attrs that you want to exclude or create
the
array elsewhere in the class and use it here
default_except = [:created_at, :updated_at]
options[:except] = (options[:except] ? options[:except] +
default_except
: default_except)
ar_to_xml(options, &blk)
end
end

If you won’t need the custom XML everywhere, you can remember to call
User.ar_to_xml (or whatever you name it), or you could create a class
that
composes a User and does the custom formatting.

Regards,
Craig

Craig D. wrote:

By the way, this page was the inspiration for my last reply:

http://ryandaigle.com/articles/2007/4/13/what-s-new-in-edge-rails-a-more-flexible-to_xml

On Sat, Aug 30, 2008 at 11:42 AM, Craig D.

Cool. I’m doing this;

alias_method :ar_to_xml, :to_xml
def to_xml(options = {})
default_except = [:activated_at, :activation_code …]
options[:except] = (options[:except] ? options[:except] +
default_except : default_except)
ar_to_xml(options)
end

It works like a charm.