Make virtual attribute more "real"

Hello,

I have tried to tackle this one with some people on IRC, but the
proposed solution doesn’t really satisfy me, as it solves the problem
only in a special case, and not in general.

So I have two models in my rails app, say Child and Parent, where the
Parent has_many :children and the Child belongs_to :parent. I have
attributes I want the Child to have that the Parent holds, some exist
as columns in the Child that if set override, some others that only
exist in the Parent. That is realised through custom getters defined
thus:

“”"
%w{ some nifty attr_ibutes }.each do |attrib|
define_method attrib do
read_attribute("#{attrib}") || parent.send("#{attrib}")
end
end
“”"

So far so good, and everything there works very well.

My problem here is that attributes the Parent has the Child doesn’t
don’t get included in stuff like .to_xml or even .attributes. In the
example at hand, if child has the column ‘nifty’ but not ‘some’ and
the parent has both, Child.find(0).attributes yields ‘nifty’ but not
‘some’, same for Child.find(0).to_xml and so on. Is there a way to
tell the Child model that even if the attributes are virtual, I want
some of them to behave like real ones?

Regards,

Felix

Felix Schäfer wrote:

My problem here is that attributes the Parent has the Child doesn’t
don’t get included in stuff like .to_xml or even .attributes. In the
example at hand, if child has the column ‘nifty’ but not ‘some’ and
the parent has both, Child.find(0).attributes yields ‘nifty’ but not
‘some’, same for Child.find(0).to_xml and so on. Is there a way to
tell the Child model that even if the attributes are virtual, I want
some of them to behave like real ones?

http://api.rubyonrails.org/classes/ActiveRecord/XmlSerialization.html

From the bottom of the above page…

You may override the to_xml method in your ActiveRecord::Base subclasses
if you need to. The general form of doing this is
class IHaveMyOwnXML < ActiveRecord::Base
def to_xml(options = {})
options[:indent] ||= 2
xml = options[:builder] ||= Builder::XmlMarkup.new(:indent =>
options[:indent])
xml.instruct! unless options[:skip_instruct]
xml.level_one do
xml.tag!(:second_level, ‘content’)
end
end
end

Am 13.06.2009 um 01:16 schrieb Robert W.:

http://api.rubyonrails.org/classes/ActiveRecord/XmlSerialization.html

From the bottom of the above page…

Yeah, I had read that one already, and that was what I meant with a
solution for this special case: it solves the problem for to_xml, but
if I ever were to use to_yaml, I’d have to override it too, and
whatever method yields a formatted output of the model’s instance.
What I’d really like is to make the virtual fact appear real. Another
quick way that came to mind would be to just add the attributes as
columns in a migration, and leave them blank, but that makes for empty
columns and seems more of a hack than a solution.

Regards,

Felix

Am 13.06.2009 um 01:36 schrieb Felix Schäfer:

whatever method yields a formatted output of the model’s instance.
What I’d really like is to make the virtual fact appear real. Another
quick way that came to mind would be to just add the attributes as
columns in a migration, and leave them blank, but that makes for empty
columns and seems more of a hack than a solution.

As a follow-up on this one: the (dirty) hack that consists in adding a
column that basically never gets used does work, but I found a third
way apart from that and tackling .to_xml. In essence, you can
pass .to_xml some parameters to control the output of to_xml, notably
in this case the :methods parameter, which just goes and includes the
return value of said methods as attributes named after these methods
in the resulting xml. While not ideal in the sense that would have
like it, it seems less deep-going than defining a custom .to_xml.

Regards,

Felix