Rendering User attributes in XML

Neil Cauldwell 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.

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

Fred

Frederick Cheung 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 Cheung 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

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

Frederick Cheung 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

Craig Demyanovich 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?

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?

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

Craig Demyanovich 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.

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

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

Craig Demyanovich 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 Demyanovich

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.