Module: ActiveRecord::AttributeViews
- Defined in:
- lib/active_record/attribute_views.rb
Overview
Attribute views translate between value object in your application and columns in your database. A value object is basically any object that represents a value, for example an IP address or a rectangle. A database has a limited number of values it can represent internally. In order to store value object we need some sort of conversion from the value object to database columns. In order to read the value object we need a conversion from columns to a value object.
Note that attribute views are a really flexible concept and in some cases it’s perfectly fine to use a string as the value object. Later on we will look at an example of this.
Defining views
In order to create an attribute view you need to create a class that takes care of the conversion between column values and your value object. The easiest way to create a view class is by subclassing from ActiveRecord::AttributeView and implementing two methods: load and parse.
The load method receives the column values from the record and returns the value object. The parse method receives the value object and returns a list of column values.
Let’s assume we want to describe a plot in the lots table with the following schema:
ActiveRecord::Schema.define do
create_table :lots do |t|
t.integer :price_in_cents
t.integer :position_x
t.integer :position_y
t.integer :position_width
t.integer :position_height
end
end
In our application we’re going to handle the position of the Lot very often so we want to access it through a value object. We write the following value object to represent it as a rectangle:
class Rectangle
attr_accessor :x1, :y1, :x2, :y2
def initialize(x1, y1, x2, y2)
@x1, @y1, @x2, @y2 = x1, y1, x2, y2
end
end
class Lot < ActiveRecord::Base
views :position, :as => RectangleView.new(:position_x, :position_y, :position_width, :position_height)
end
class RectangleView < ActiveRecord::AttributeView
def load(x, y, width, height)
Rectangle.new(x, y, x + width, y + height)
end
def parse(rectangle)
[rectangle.x1, rectangle.y1, (rectangle.x2 - rectangle.x1), (rectangle.y2 - rectangle.y1)]
end
end
Instance Method Summary collapse
Instance Method Details
#views(name, options = {}) ⇒ Object
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/active_record/attribute_views.rb', line 82 def views(name, ={}) .assert_valid_keys(:as) raise ArgumentError, "Please specify a view object with the :as option" unless .has_key?(:as) view_name = "#{name}_view" define_method(view_name) do [:as] end class_eval " def \#{name} # def starts_at\n \#{view_name}.get(self) # starts_at_view.get(self)\n end # end\n READER_METHODS\n \n class_eval <<-WRITER_METHODS, __FILE__, __LINE__\n def \#{name}_before_type_cast # def starts_at_before_type_cast\n @\#{name}_before_type_cast || \#{name} # @starts_at_before_type_cast || starts_at\n end # end\n \n def \#{name}=(value) # def starts_at=(value)\n @\#{name}_before_type_cast = value # @starts_at_before_type_cast = value\n \#{view_name}.set(self, value) # starts_at_view.set(self, value)\n end # end\n WRITER_METHODS\nend\n", __FILE__, __LINE__ |