Smart things with rich-types

17 views
Skip to first unread message

Ritchie Young

unread,
Jun 7, 2009, 10:32:05 PM6/7/09
to hobo...@googlegroups.com
Hi,

I've just started with Hobo about a week ago and I'm really enjoying
it. It definitely makes vanilla Rails seem like hard work.

I was wondering if there are plans to extend the rich fields system. I
see at present it supports validation and representation to HTML but
it doesn't seem to support conversion for storage.

An example would be currency. I want to store an amount of money in
cents but allow it to be entered and display it in a (culturally
insensitive) dollars.cents format. I can convert it in the model by
overriding the attribute accessors for it:

fields do
price :integer
end

def price() self[:price].as_dollars_and_cents; end
def price=(dollars) self[:price]=convert_to_cents(dollars); end

By writing a Rails initializer (http://pastie.org/504098), I can get it down to:

fields do
price :integer
end

treat_as_currency :price

But what would be really cool would be to get it down to:

fields do
price :currency
end

Any thoughts on how/whether this could/should be achieved?

Thanks
Ritchie

Tom Locke

unread,
Jun 8, 2009, 5:22:48 AM6/8/09
to hobo...@googlegroups.com
There's no way to do this with rich-types right now but I think it's a
great idea.

Could you put a ticket on the Hobo lighthouse tagged 'enhancement'.

I don't think it will make it in to 1.0 but I'd like to see this added.

Thanks

Tom

Montgomery Kosma

unread,
Jun 8, 2009, 2:51:55 PM6/8/09
to Hobo Users
with Tom's recent patch, at least, Hobo deals with BigDecimal quite
well, making currency a snap.

That said, I agree, would love to see this extension. In my case,
developing a business process management tool, I have numerous stats
and figures that I want the user to be able to flag as "estimated."
As of now, those are separate boolean fields in the model associated
with various bigdecimal or integer values. Would love to be able to
define a superclass (EstimatedBigDecimal) that captures all the
functionality that goes with it (computation as well as the database
and GUI elements).

kevinpfromnm

unread,
Jun 8, 2009, 7:13:42 PM6/8/09
to Hobo Users
You might be able to get by for now with a class for your object and
serialize it. I haven't done anything with rich types yet so I can't
say whether or not it's doable to encompass a serialized custom class
with it or not.

davidmathers

unread,
Jun 10, 2009, 5:07:01 AM6/10/09
to Hobo Users
On Jun 7, 7:32 pm, Ritchie Young <ritch...@gmail.com> wrote:
>
> An example would be currency. I want to store an amount of money in
> cents but allow it to be entered and display it in a (culturally
> insensitive) dollars.cents format.

I've been away from Hobo for a while (my work laptop was stolen) but
this is exactly what I do with my Hobo cents type. Here's the code:

http://gist.github.com/127101

Values get stored as cents in an integer field in the db, get loaded
as Ruby fixnums, and get converted for display. I might be missing
something but I don't understand why you want to convert for storage
rather than display.

Something I would like is the ability to save a single type to
multiple db columns. That way the cents type could have both a cents
value and a currency type value.

I had thought about using the cents type for a cookbook recipe back
when I first wrote it, but now that we have hobo-contrib it might be a
good idea to add a section for rich types to that. Thoughts Bryan?

-david

Bryan Larsen

unread,
Jun 10, 2009, 7:35:35 AM6/10/09
to hobo...@googlegroups.com
>
> I had thought about using the cents type for a cookbook recipe back
> when I first wrote it, but now that we have hobo-contrib it might be a
> good idea to add a section for rich types to that. Thoughts Bryan?
>

I think hobo-contrib is an excellent place for something like that.

cheers,
Bryan

Bryan Larsen

unread,
Jun 10, 2009, 8:26:27 AM6/10/09
to hobo...@googlegroups.com
Montgomery Kosma wrote:
> with Tom's recent patch, at least, Hobo deals with BigDecimal quite
> well, making currency a snap.
>
> That said, I agree, would love to see this extension. In my case,
> developing a business process management tool, I have numerous stats
> and figures that I want the user to be able to flag as "estimated."
> As of now, those are separate boolean fields in the model associated
> with various bigdecimal or integer values. Would love to be able to
> define a superclass (EstimatedBigDecimal) that captures all the
> functionality that goes with it (computation as well as the database
> and GUI elements).
>


What I've done is just define a separate table. IE,
EstimatedBigDecimal is stored in the estimated_big_decimals table, and
classes that use it have `belongs_to :price, :class =>
"EstimatedBigDecimal"`.

It seems wrong, but it works smoothly and allows me to define a custom
view, custom input, et cetera for it.

Now granted, my classes weren't quite as simple as EstimatedBigDecimal,
but simple enough that a separate table certainly seemed questionable!

cheers,
Bryan

Ritchie Young

unread,
Jun 10, 2009, 10:49:00 PM6/10/09
to hobo...@googlegroups.com
I appreciate all the feedback on this but the more I thought about it, the more I realised I wasn't really sure what I was asking for.

I think I meant for Hobo to detect if the rich-type had particular callback methods and, if so, to hook them into the model's read and write methods for that field. In other words, to do automatically, what I was doing in my example.

This behaviour could be confusing though because the application author might have some other valid reason for wanting to override those reader and writer methods. I don't know if there's a resilient way to do this.

Then I started to think that what I really wanted was a hook into the view/controller layers. The <view/> tag and I think the <input/> tags already call to_s on the object being displayed. So by overriding that in the rich-type we're half-way there. If we could have a from_s method on the rich type that was called when data was written we could do the conversion there. Only, from_s would have to be a class method or a constructor because the rich-types inherit from the base types.

At this point I read about ActiveRecord's Aggregate functionality, which seems to overlap this somewhat, and got really confused. Which is why I haven't logged an enhancement request on lighthouse.

I'm getting by quite nicely, for now, with my original solution: store it as an integer and convert it in the field getters and setters.


/Ritchie

kevinpfromnm

unread,
Jun 13, 2009, 5:59:46 PM6/13/09
to Hobo Users
You can override the assignment operator for the particular field to
be able to do your particular logic on assignment. Then just do a
write_attribute to save your info in the field. I don't know if that
covers all the ways hobo might try to create a new model or not
though. I haven't had any problem with an 0.7.5 app that uses that
technique though.

Matt Jones

unread,
Jun 13, 2009, 6:07:23 PM6/13/09
to hobo...@googlegroups.com
I'm working on migrating a 0.7.2 codebase to current Hobo that does
some things that sound a lot like this; look for more info when I get
the code cleaned up some...

--Matt Jones

Matt Jones

unread,
Sep 6, 2009, 5:36:12 AM9/6/09
to hobo...@googlegroups.com
As promised! There's a single commit in the indexgen branch that does
this. Here's an example, taken from the code that inspired the feature:


--- phone_number.rb

class Hobo::PhoneNumber < String

COLUMN_TYPE = :string

def format
data = self.gsub(/[.() -]*/, '')
data =~ /^\d{10}$/ ? data.gsub(/^(\d{3})(\d{3})(\d{4})$/, '\1-\2-
\3') : self
end

def validate
"is not a valid phone number" unless
self.blank? || self =~ /^[2-9]\d{2}-\d{3}-\d{4}$/
end

end

HoboFields.field_types[:phone_number] = Hobo::PhoneNumber

-------------------------

Not tested formatting anything *other* than strings; maybe somebody
can try it out for the money example from this thread?

--Matt Jones
Reply all
Reply to author
Forward
0 new messages