Property
¶ ↑
Wrap model properties into a single database column and declare properties from within the model.
website: zenadmin.org/635
license: MIT
Status: Beta¶ ↑
The gem works fine, even though it still needs some more features like property definition changes detections and migrations.
Usage¶ ↑
You first need to create a migration to add a ‘text’ field named ‘properties’ to your model. Choose a text format that is really long (otherwize your data will be truncated and the property will fail to decode => error). Do something like this:
class AddPropertyToContact < ActiveRecord::Migration def self.up if ActiveRecord::Base.configurations[RAILS_ENV]['adapter'] == 'mysql' execute "ALTER TABLE contacts ADD COLUMN properties LONGTEXT" else add_column :contacts, :properties, :text end end def self.down remove_column :contacts, :properties end end
Once your database is ready, you need to declare the property columns:
class Contact < ActiveRecord::Base include Property property do |p| p.string 'first_name', 'name', 'phone' p.datetime 'contacted_at', :default => Proc.new {Time.now} end end
You can now read property values with:
@contact.prop['first_name'] @contact.first_name
And set them with:
@contact.update_attributes('first_name' => 'Mahatma') @contact.prop['name'] = 'Gandhi' @contact.name = 'Gandhi'
Roles¶ ↑
Properties would not be really fun if you could not add new properties to your instances depending on what the object does. First define the roles:
@picture = Property::Role.new do |p| p.integer :width, :default => :get_width p.integer :height, :default => :get_height p.string 'camera' p.string 'location' p.actions do # Define new methods to insert into model def get_width image.width end def get_height image.height end def image raise 'Missing file' unless @file @image ||= ImageBuilder(@file) end end end
And then, either when creating new pictures or updating them, you need to include the role:
@model.has_role @picture
The model now has the picture’s properties defined, with accessors like @model.camera, methods like @model.image, get_with, etc and default values will be fetched on save.
Note that you do not need to include a role just to read the data as long as you use the ‘prop’ accessor.
StoredRole¶ ↑
The dynamic nature of the Property
gem goes to the point where you can store your property definitions in the database by using the StoredRole and StoredColumn modules.
External storage¶ ↑
You might need to define properties in a model but store them in another model (versioning). In this case you can simply use ‘store_properties_in’ class method:
class Contact < ActiveRecord::Base include Property store_properties_in :version property do |p| p.string 'name', 'first_name' p.string 'childhood', :default => 'happy' end end
Doing so will not touch the storage class. All property definitions, validations and method definitions are executed on the ‘Contact’ class.
Indexing support¶ ↑
The property gem lets you very easily export content from the packed data to any kind of external table. Using a key/value tables:
class Contact < ActiveRecord::Base include Property property do |p| p.string 'name', :indexed => true p.string 'first_name', :index => Proc.new {|rec| { 'fullname' => rec.fullname }} p.index(:string) do |record| { 'fulltext' => "name:#{record.name} first_name:#{record.first_name}", "name_#{record.lang}" => record.name } end end end
Using a custom indexer, you can group indexed values together in a single record. This can be interesting if you have some legacy code or queries that need direct access to some values:
class Contact < ActiveRecord::Base include Property property do |p| p.string 'name' p.string 'first_name' p.index(ContactIndexer) do |record| { 'name' => record.name, 'first_name' => record.first_name, } end end end
Please read the docs for details: zenadmin.org/635
Developping property and testing¶ ↑
As of 2015, you need ruby 1.8.7 and the following gems in order to run the test suite.
gem install rdoc-data; rdoc-data --install gem install shoulda --version=2.10.3 gem install activerecord --version=2.3.18 gem install sqlite3 --version=1.3.5 gem install json --version=1.5.1 gem install jeweler --version=1.8.3