define_schema for Active Resource

Skip to first unread message


Dec 15, 2009, 4:58:26 AM12/15/09
to Ruby on Rails: Core
So, following on from the original discussion-thread here:

I've built some baseline functionality for defining a schema for an
Active Resource.

Code available as a patch here:

and a more-readable combined diff here:

What you can now do is this:

class FlickrPhoto << ActiveResource::Base

define_schema do |s|
s.string :photo, :title
s.integer :width, :height
s.float :some_other_attribute
s.attribute 'and_another', 'string'

validates_presence_of :photo
validates_numericality_of :width, :height

# this works
my_photo = => 'photo_stream_here', :title =>
'eben', :tags => ['cat'])
my_photo.valid? # => true # => true # 'photo_stream_here'

# and now, so does this:
new_photo =
new_photo.respond_to? :photo # => true # => nil
new_photo.valid? # => false

new_photo.known_attributes # => ['photo', 'title', 'height',
'width', 'some_other_attribute', 'and_another']

# and if you fetch and existing one:
a_photo = FlickrPhoto.find(1) # <FlickrPhoto><photo>abcdef</
FlickrPhoto> # => 'abcdef'
a_photo.width # => '123' # note: still a
a_photo.instance_attribute # => '456' # note: also a string

a_photo.known_attributes # => ['photo', 'title', 'height',
'width', 'some_other_attribute', 'and_another', 'instance_attribute']

new_photo.respond_to? 'instance_attribute' # => false (because it's
not a known_attribute)

More details on what/how in the rdoc for define_schema :)

To summarise:
1) You can define a schema using 'define_schema' and passing a block,
or passing a hash to 'schema='
2) this populates a set of 'known_attributes' that are added to the
list of attributes currently on an instance (if there's no schema,
this means that the known_attributes equals the existing attributes on
the instance - as it always has done).
3) known attributes will return 'true' to a 'respond_to?' and will not
cause a 'NoMethodError' if invoked
4) it will also store the 'attribute type' against each attribute -
currently this does nothing... but my next step is to add a typecast
based on this, along with "attributes_before_typecast" ala Active
Record. This will be extremely useful for integer values as I've found
my own code peppered with "to_i" checks for attributes that I already
know are meant to be integers :P
5) an extension will also allow us to pass in options. The only
sensible one that I can see so far is ":default => 'blah') which will,
of course, set up known attributes with their given defaults - unless
otherwise specified.


Joshua Peek

Dec 16, 2009, 12:59:42 PM12/16/09
to Ruby on Rails: Core
Looks good.

DHH would recommend using instance_eval for the schema block just to
clean up the "s."

On Dec 15, 3:58 am, taryneast <> wrote:
> So, following on from the original discussion-thread here:


Dec 17, 2009, 4:32:02 AM12/17/09
to Ruby on Rails: Core
Ah ok. I wasn't sure how to do that, and figured I'd follow the
'create_table' syntax.
I'll have a go at the instance_eval version though. Always good to
learn new stuff. :)
Reply all
Reply to author
0 new messages