Wednesday, August 29, 2012

Introducing Classmeta for Dynamic Class Creation in Rails

Take a look at Classmeta, now in GitHub and Rubygems.

To get started, in your Rails 3.2+ project, add this to your Gemfile. For this example, I'm using the alpha initial version. Please work with a later version and look at the README in GitHub for the latest usage:

gem 'classmeta', '= 0.0.1'

Install it:

bundle install

Open Rails console:

rails c

Try it:

YourModel.meta(:echo)
YourModel.meta(:echo).name
YourModel.meta(:echo, {:say => 'Hello World!'})
YourModel.named_meta('Fabular', :echo, {:say => 'Hello World!'})
Fabular.all

Now, to do something useful with it, lets add a transformer.

Add this to config/environment.rb:

And this to app/models/standard_transformer.rb, or wherever is on load path:

class StandardTransformer
  def transform(klazz, options)
    klazz.class_eval "self._accessible_attributes[:default] = #{options[:attrs].inspect}" if options[:attrs]
  end
end

Now you can change an association in your model from:

has_many :passengers, class_name: 'Person'

to use the Classmeta generated class:

has_many :passengers, class_name: Person.meta(:std, attrs: [:name]).name

With a few handfuls of characters in the association, you created a brand new class that is a dup of Person with some changes.

Classmeta::Options.configure({
  :transformers => {
    :std => StandardTransformer
  }
})

You can also name the model to something sensible to work with it as needed:

has_many :passengers, class_name: Person.named_meta(NameOnlyPerson, :std, attrs: [:name]).name

This is alpha-level code, and plenty of magic, so use at your own risk and let us know if you have any problems with it on the GitHub page in the Issues section.

No comments: