# Extend at This gem allows you to extend the columns from your model without migrations, you can, i.e., develop your own content types, like in Drupal ## Installation gem install extend_at ### Rails 3 Add in your Gemfile: gem 'extend_at', :git => 'git://github.com/anga/extend_at.git' ## Usage Only you need to add the next line in your model. extend_at :configuration For example: class User < ActiveRecord::Base extend_at :extra end Now you can write your configuration like: user.extra.private_photos = true user.extra.subscribe_to_news = false user.extra.perfil_description = '' user.save ### Columns configuration You can configurate each column. #### Set column type You can set the type of the colum. class User < ActiveRecord::Base extend_at :extra, :columns => { :private_photos => { :type => :boolean }, :age => { :type => :get_type }, :perfil_description => { :type => lambda { String } }, :last_loggin => { :type => Time.now.class }, :subscribe_to_rss => :get_rss_config } protected def get_type Fixnum end def get_rss_config { :type => :boolean } end end You can use any class, but if you need use boolean values, you must use :boolean. #### Set default value class User < ActiveRecord::Base extend_at :extra, :columns => { :private_photos => { :type => :boolean, :default => true }, :age => { :type => :get_type, :default => 1 }, :perfil_description => { :type => lambda { String }, :default => :get_default_perfil_description }, :last_loggin => { :type => Time.now.class, :default => lambda { self.created_at.time } }, :subscribe_to_rss => :get_rss_config } protected def get_type Fixnum end def get_rss_config { :type => :boolean, :default => true } end def get_default_perfil_description Description.where(:user_id => self.id).default end end #### Set validation class User < ActiveRecord::Base extend_at :extra, :columns => { :private_photos => { :type => :boolean, :default => true }, :age => { :type => :get_type, :default => 1, :validate => lambda { |age| errors.add :config_age, "Are you Matusalén?" if age > 150 errors.add :config_age, "Are you a fetus?" if age <= 0 } }, :perfil_description => { :type => lambda { String }, :default => :get_default_perfil_description, :lambda => :must_not_have_strong_language }, :last_loggin => { :type => Time.now.class, :default => lambda { self.created_at.time }, :validate => lambda { |time| errors.add :config_last_loggin, "You can't loggin in the future" if time > Time.now } }, :subscribe_to_rss => :get_rss_config } protected STRONG_WORD = [ #... ] def get_type Fixnum end def get_rss_config { :type => :boolean, :default => true } end def get_default_perfil_description Description.where(:user_id => self.id).default end def must_not_have_strong_language(desc) errors.add :cofig_perfil_description, "You must not have strong language" if desc =~ /(#{STRONG_WORD.join('|')})/ end end ### Integration in the views If you like to use come configuration variable in your views you only need put the name of the input like :config_name, for example: <% form_for(@user) do |f| %> ...
<%= f.label :extra_private_photos %>
<%= f.check_box :extra_private_photos %>
... <% end %> ### Tips If you like to do something more dynamic, like create columns and validations depending of some model or configuration, the you can do something like this: class User < ActiveRecord::Base extend_at :extra, :columns => :get_columns serialize :columns_name protected def get_columns columns = {} columns_name.each do |name| config = ColumConfig.where(:user_id => self.id, :column => name).first columns[name.to_sym] = { :type => eval(config.class_type), :default => config.default_value, :validate => get_validation(config.validation) } end columns end # Accept a name of a validation and return the Proc with the validation code def get_validation(validation_type) # ... end end This code read the configuration of the columns when you acces to extra column