Rails 4.0 – current master branch at the time of this writing – has recently got a small – yet very useful – addition: ActiveModel::Model . The implementation is really simple, as you can see below:

module ActiveModel module Model def self.included(base) base.class_eval do extend ActiveModel::Naming extend ActiveModel::Translation include ActiveModel::Validations include ActiveModel::Conversion end end def initialize(params={}) params.each do |attr, value| self.public_send("#{attr}=", value) end if params end def persisted? false end end end

Quite straightforward, huh? But what does it do, and what are we supposed to do with it?

ActiveModel::Model: Basic Model implementation

According to the docs, ActiveModel::Model includes all the required interface for an object to interact with ActionPack , using different ActiveModel modules. It includes model name instrospection, conversions, translations and validations. In addition to that, it allows you to initialize the object with a hash of attributes, pretty much like ActiveRecord does.

Wait, what? In short: you can easily extend ActiveModel::Model in a normal Ruby class and use instances of that class with helpers like form_for , dom_id / dom_class , and any other ActionView helper, as you do with ActiveRecord objects. It also gives you known method helpers such as human_attribute_name .

A minimal implementation could be:

class Person include ActiveModel::Model attr_accessor :name, :age validates_presence_of :name end person = Person.new(:name => 'bob', :age => '18') person.name # => 'bob' person.age # => 18 person.valid? # => true

This is really handy, considering that before this addition, we’d have to add all that code to have a model up and running to use with ActionView's form_for , for instance. Ok, it is not that much code to add, but now we don’t even need to remember which modules are required for such integration. And I have to add that I’ve been creating similar classes in different applications lately. Take a moment to think about a contact form, that does not need to be tied to a database: it’s a common scenario to implement using ActiveModel::Model .

Extending Basic Model even more

Note that, by default, ActiveModel::Model implements persisted? to return false , which is the most common case. For instance, when used with form_for , this means that the generated url would post to the create action. You may want to override it in your class to simulate a different scenario:

class Person include ActiveModel::Model attr_accessor :id, :name def persisted? self.id == 1 end end person = Person.new(:id => 1, :name => 'bob') person.persisted? # => true

Besides that, if for some reason you need to run code on initialize , make sure you call super if you want the attributes hash initialization to happen.

class Person include ActiveModel::Model attr_accessor :id, :name, :omg def initialize(attributes) super @omg ||= true end end person = Person.new(:id => 1, :name => 'bob') person.omg # => true

And remember that, at the end, this is all Ruby: you can include any other module of your own and other ActiveModel modules easily in your class. For instance, lets add callbacks to our model to mimic ActiveRecord's save functionality:

class Person include ActiveModel::Model extend ActiveModel::Callbacks define_model_callbacks :save attr_accessor :id, :name # Just check validity, and if so, trigger callbacks. def save if valid? run_callbacks(:save) { true } else false end end end

This gives you before_save , after_save and around_save callbacks. Quick and easy, huh?

Wrapping up

ActiveModel::Model is a really small, handy addition to Rails 4.0, which helps us to get classes that act more like ActiveRecord and easily integrate with ActionPack .

For more detailed information on other features available, please refer to the specific modules included in ActiveModel::Model . Each module includes plenty of docs explaining its functionality. Apart from these included modules, ActiveModel itself has a bunch of useful stuff to add to your Ruby classes that are really worth checking out.

This is the kind of thing that makes me a happier Rails developer every day. What about you, what makes you a happier Rails developer? Please take a moment to tell us in the comments section below 🙂