Forum: Ruby on Rails [TIP] Making an intelligent form fields

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
2a73a242ac582b27e841b4bce6ba1373?d=identicon&s=25 Kamil Kukura (Guest)
on 2006-03-09 23:32
(Received via mailing list)
After searching arround I found a quite smart solution to me for binding
form fields to model in an active way. I use aggregations with single
value objects such as

class Percentage
   attr_accessor :value

   def initialize(value)
     @value = (value.is_a? String) ? value.tr(' %', '').to_f : value
   end

   def to_s
     return unless value
     sprintf('%.2f %%', value)
   end
end

This is an object that takes either float or string (with possible %
character in it) and viewed as string looks like "1.23 %". So I can
easily create an intelligent "shadow" attribute for interaction:

     composed_of :i_discount_rate, :class_name => 'Percentage',
                 :mapping => %w(discount_rate value)

Using i_discount_rate in form it makes value of discount_rate shown in
text field pretty with % sign. But we cannot pass it to the model
because in mass-assignment everything is just string from request.

So I used reflection on aggregation and as attributes are about to be
processed, they are "objectized", so attributes[:i_discount_rate] will
gain a real Percentage object:

    def attributes=(attributes)
      attributes.each do |param, value|
        aggregation = self.class.reflect_on_aggregation(param.to_sym)
        if aggregation
          attributes[param] = aggregation.klass.new(value)
        end
      end

      super(attributes)
    end

Now an user can enter "2%", "2.0 %", "2.1  %  ", etc. and everything is
acceptable. We can now create value object for money so field "54,20
EUR" is perfectly acceptable. And there can be objects for entering date
like "+3 days" and so on.

The mechanizm for "i_attributes" can be enhanced similiary as Date is
expanded into form fields. So for example we can have aggregation

    composed_of :i_amount, :class_name => 'Amount',
                :map => [%w(a_count count), %w(a_units units)]

And then helper used like

    amount_field 'order_item', 'i_amount'

which renders to one text field and one select box such as:

    <input type="text" name="order_item[i_amount(count)]"/>
    <select name="order_item[i_amount(units)]">
      <option value="l">liters</option>
      <option value="t">tons</option>
      <option value="pc">pieces</option>
    </select>



That's it.

--
Kamil
8a8ba7e85e336beb1304453ef20a7470?d=identicon&s=25 Karel Miarka (Guest)
on 2006-05-04 08:37
Great! Just what I was looking for.

Thanks,
Karel
This topic is locked and can not be replied to.