After 4 months of our last major version release, we’re releasing Devise 2.1.0, which includes several bug fixes, some new features and the removal of features deprecated on Devise 2.0. If you’re eager to do the update, please check Devise’s wiki page about Upgrading from 2.0 to 2.1. You can also check the changelog or the commits between 2.0.4 and 2.1.0.

Encrytable is now a gem

As it was only used for old encryption algorithms like sha1 or md5, we have extracted encryptable module to a separated ruby gem. So, if you’re using the encryptable module, you should only require it on your Gemfile and you’re good to go!

Check fields

To allow a developer to cherry-pick which features they want to add to their models, Devise splits its behaviors into modules. One of the consequences of such splitting is that you don’t know if the persistence layer provides all fields required by the behavior. For example, the database authenticatable module requires a encrypted_password field. If the field does not exist, you will end up getting an error during a request. Usually those fields are automatically added to the migration when you call the devise generator, but if you decide to include a module after, you can easily forget to add the new fields.

That said, in order to provide faster feedback, Devise now has a method that checks if a given class is missing any of the required fields and raises an error if so. You can call this method as follow (in case your Devise class is User):

Devise::Models.check_fields!(User)

We’ve implemented this feature in an agnostic way, to not depend on a specific ORM, but only to verify if the instance responds to the required fields. So even if your ORM does everything through method_missing, you should be able to use this method (we’re relying that you also have implemented a working respond_to?, which is strongly recommendeded when using method_missing).

When check_fields! is called, Devise will detect the included modules in the given class and, if there is a missing attribute, it will raise a Devise::Models::MissingAttribute exception with a message telling you all required fields that doesn’t exist. You can easily use that method with your favorite test framework:

Devise::Models.check_fields!(User)

And then you will be able to check if your migrations have added the correct fields to your database.

A message to module maintainers

If you’re a maintainer of a Devise module, you should add a method to each of your modules called self.required_fields(klass) that returns an array of required fields. If the method is absent, you will get a deprecation warning.

UPDATE: Fixed a class name and corrected a grammar error.

Today I want to show you a project I’ve started over a year ago, during Mendicant University core skills course. For those who don’t know, Mendicant University is a group of skilled software developers that offer courses, mentoring, and help out the community, started by Gregory Brown, and that nowadays counts with some other awesome folks as part of the staff. I highly recommend taking a look at and enrolling.

Back to I18n, during Mendicant University we were supposed to create a project in Ruby, not specifically with Rails, and I decided to scratch my own itch by trying to solve a problem we usually have in Brazil: receiving date/time/numeric input from user interface. I know and have already used the delocalized gem, and it works quite nice, but sometimes I felt a bit uncomfortable about how it handled some parts of localization/parsing. This is mainly due to the need to monkey patch both ActiveRecord to handle input, and ActionView to handle output. Besides that, and most important, I had to come up with some project and I thought that’d be a good challenge :D .

The main goal of this project is to provide a proxy object to use with your ORM (currently ActiveRecord only) that will be responsible for localizing and parsing the date/time/numeric attributes when getting or setting their values, respectively. Lets see some quick examples:

# Include the proxy in your model
class Product < ActiveRecord::Base
  include I18n::Alchemy
end
 
# Grab your object from the database
@product   = Product.first
# Instantiate the localized proxy
@localized = @product.localized

Now that we have a localized proxy for the @product object, we can get/set numeric attributes with localized values, such as:

@localized.price = "1.99"
 
@product.price   # => 1.99
@localized.price # => "1.99"
 
I18n.with_locale :pt do
  @localized.price = "1,88"
 
  @product.price   # => 1.88
  @localized.price # => "1,88"
end

And also date/time attributes, for instance:

@localized.released_at = "12/31/2011"
 
@product.released_at   # => Date.new(2011, 12, 31)
@localized.released_at # => "12/31/2011"
 
I18n.with_locale :pt do
  @localized.released_at = "31/12/2011"
 
  @product.released_at   # => Date.new(2011, 12, 31)
  @localized.released_at # => "31/12/2011"
end

I18n Alchemy can also receive a hash of attributes, the same way you use with your models when calling new. That means you can use it like this:

# You could be using params[:product] for instance.
I18n.with_locale :pt do
  @localized = @product.localized(:price => "1,88") 
 
  @product.price   # => 1.88
  @localized.price # => "1,88"
end

The parsing/localization formats are basically the same ones you already use in your Rails application. You can check the basic locale configuration for I18n Alchemy in its README on github.

Wrapping up

I18n Alchemy is a small and new project which solves most of the problems we commonly face when dealing with localization and parsing of date/time/numeric values. It is tested with Rails 3.0, 3.1 and 3.2 and works with all the basic methods, such as attributes=, assign_attributes, update_attributes and nested attributes as well.

It was a really fun time creating it during Mendicant University, and it took a long time until I decided to release it as a gem. There is still a bunch of things to do, but I wanted to ask you to give it a try and let me know about any feedback you have.

As a side note, if you are interested in knowing more about the design decisions that led this project, you may want to take a look at Gregory Brown’s post on Ruby Best Practices, entitled “Issue #23: SOLID Design Principles”, more specifically in the Open/closed principle topic.

I’m releasing the first 0.0.1 version today, and I hope you find it useful. Have any comments? Let us know!

Hello friends!

We are excited to present our new visual identity and website.

We felt that it was time to give a step further into the way people see us. Our previous visual identity was very dense and the logo had a very strong appeal to “engineering”. It felt very solid and we liked it. But since we’ve founded Plataformatec we have learnt lots of new things, launched dozens of apps and we’ve met new great clients. Because of this, we brought new people onboard to complement us, with skills we didn’t have before.

Today, our team has engineers, designers, agile project managers and some business guys too. It would be more accurate if our visual identity incorporated them too. We still like to be seen as software engineers, but now, our team and services scope has grown.

We hope you like our new look.

Don’t be shy! Take a look into our new website and our page on Facebook and tell us what you think.

By the way, we’ll keep using @plataformatec twitter account for announcements, so keep following us. ;)

 

 

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 :)

The Carnival is over in Brazil but we are still partying at Plataformatec by bringing you a complete new release of SimpleForm. This time is not a small bump though, it’s a shiny new version: SimpleForm 2.0, that comes with a bunch of new features and customizations, a new wrapper API to create custom input stacks and a great integration with Twitter Bootstrap.

Wrappers API

The new wrappers API is here in place of the old components option (besides some other *_tag and *_class configs), to add more flexibility to the way you build SimpleForm inputs. Here is an example of the default wrapper config that ships with SimpleForm when you run its install generator:

config.wrappers :default, :class => :input,
  :hint_class => :field_with_hint, :error_class => :field_with_errors do |b|
  ## Extensions enabled by default
  # Any of these extensions can be disabled for a
  # given input by passing: `f.input EXTENSION_NAME => false`.
  # You can make any of these extensions optional by
  # renaming `b.use` to `b.optional`.
 
  # Determines whether to use HTML5 (:email, :url, ...)
  # and required attributes
  b.use :html5
 
  # Calculates placeholders automatically from I18n
  # You can also pass a string as f.input :placeholder => "Placeholder"
  b.use :placeholder
 
  ## Optional extensions
  # They are disabled unless you pass `f.input EXTENSION_NAME => :lookup`
  # to the input. If so, they will retrieve the values from the model
  # if any exists. If you want to enable the lookup for any of those
  # extensions by default, you can change `b.optional` to `b.use`.
 
  # Calculates maxlength from length validations for string inputs
  b.optional :maxlength
 
  # Calculates pattern from format validations for string inputs
  b.optional :pattern
 
  # Calculates min and max from length validations for numeric inputs
  b.optional :min_max
 
  # Calculates readonly automatically from readonly attributes
  b.optional :readonly
 
  ## Inputs
  b.use :label_input
  b.use :hint,  :wrap_with => { :tag => :span, :class => :hint }
  b.use :error, :wrap_with => { :tag => :span, :class => :error }
end

Wrappers are used by the form builder to generate a complete input. You can remove any component from the wrapper, change the order or even add your own to the stack.

The :default wrapper is going to be used in all forms by default. You can also select which wrapper to use per form, by naming them:

# Given you added this wrapper in your SimpleForm initializer:
config.wrappers :small do |b|
  b.use :placeholder
  b.use :label_input
end
 
# Uses the :small wrapper for all inputs in this form.
simple_form_for @user, :wrapper => :small do |f|
  f.input :name
end

Or you can just pick a different wrapper in a specific input if you want:

# Uses the default wrapper for other inputs, and :small for :name.
simple_form_for @user do |f|
  f.input :name, :wrapper => :small
end

You can see a more detailed description of the new wrappers API in the documentation.

Twitter Bootstrap

The second big change in SimpleForm 2.0 is out of the box Bootstrap integration. SimpleForm now ships with a generator option to initialize your application with a set of specific wrappers customized for Bootstrap. To get them, just run in your terminal, inside a Rails application (with SimpleForm already installed):

rails generate simple_form:install --bootstrap

This gives you the default SimpleForm initializer in config/initializers/simple_form.rb with some extra integration code added for Bootstrap. For example, here is the default wrapper:

config.wrappers :bootstrap, :tag => 'div', :class => 'control-group', 
  :error_class => 'error' do |b|
  b.use :placeholder
  b.use :label
  b.wrapper :tag => 'div', :class => 'controls' do |ba|
    ba.use :input
    ba.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
    ba.use :hint,  :wrap_with => { :tag => 'p', :class => 'help-block' }
  end
end

This wrapper is setup with the same structure that Bootstrap expects and is set to be the default wrapper in your application. This is the killer feature in SimpleForm 2.0: the Bootstrap integration is not inside SimpleForm but all in your application. This means that, if you want to move away or customize Bootstrap in the future, you don’t need to monkey patch SimpleForm, everything is in your app!

We’ve set up a live example application showing most of the SimpleForm inputs integrated with Twitter Bootstrap, make sure you check it out! The application code is on github.

Keep reading this blog post to find out the other changes and deprecations that gave SimpleForm all this extra flexibility, allowing it to be easily integrated with Twitter Bootstrap 2.0.

New configs

SimpleForm 2.0 comes with some new configs to ease its integration with Bootstrap and to make your daily work even more flexible:

  • default_wrapper: defines the default wrapper to be used when no one is given.
  • button_class: defines a class to add for all buttons.
  • boolean_style: change the way booleans (mainly check boxes and radio buttons) are shown: :inline (the default) uses the same structure as before, checkbox + label; :nested (generated for new apps) puts the checkbox inside the label, as label > checkbox.
  • collection_wrapper_class: class to add in all collections (check boxes / radio buttons), given collection_wrapper_tag is set.
  • item_wrapper_class: class to add to all items in a collection.
  • generate_additional_classes_for: allows you to specify whether to generate the extra css classes for inputs, labels and wrappers. By default SimpleForm always generate all classes, such as input type and required info, to all of them. You can be more selective and tell SimpleForm to just add such classes to the input or wrapper, by changing this config.

Deprecations

In order to create the new wrappers API, we had to deprecate some configs and change some helpers, so here is a basic summary of what is being deprecated:

Configs

  • translate: By making placeholder and hint optional options in the wrappers API, you can already disable the automatic translation attempt that happens for these components. labels, on the other hand, are always used in forms, so we added a special config for them: translate_labels.
  • html5: this config is now part of the wrappers API, with b.use :html5, so the config option has been deprecated.
  • error_notification_id: in favor of using error_notification_class only.
  • wrapper_tag=, wrapper_class=, wrapper_error_class=, error_tag=, error_class=, hint_tag=, hint_class=, components=: all these were moved to the wrappers API structure, and are not required anymore.

Helpers

  • :radio input type: In order to integrate with Bootstrap, we had to get rid of the :as => :radio and use :as => :radio_buttons instead. The former still works, but will give you a bunch of deprecation warnings. CSS class names changed accordingly as well
  • collection_radio: has changed to collection_radio_buttons to follow the :as => :radio_buttons change. Its label class has changed as well based on the helper name.

Wrapping up

SimpleForm 2.0 comes with a lot of new features, in special the new wrappers API, to make it flexible enough to allow you to customize inputs as much as possible in an easier way, and to bring you the integrated Bootstrap structure.

Make sure you check out the new SimpleForm README and also the CHANGELOG for a full list of changes. We’ve also created an special wiki page to help you Upgrading to SimpleForm 2.0.

If you find any trouble while migrating to 2.0, or any issue with Bootstrap integration, or any other issue, please let us know in the issues tracker. And if you have any questions, make sure to send them to the mailing list, there are a lot of people there to help you.

All our development team and an amazing number of contributors put a lot of effort into this new release and we hope you will enjoy it. SimpleForm 2.0 + Bootstrap: from us, for you, with love.

Thoughts about SimpleForm 2.0? Please let us know in the comments.

We have just released Devise 2.0. This version is not a big refactoring, nor contains stellar features, it is simply another step towards a very mature authentication library.

Over the years, we have learned from our own experience and from your feedback, how to better use Devise. We’ve made changes to improve security and also to make the library more flexible. All those changes were backwards compatible, forcing us to maintain different branches of logic in the same source code to accomodate those different scenarios. Devise 2.0 simply deprecates those old scenarios so we can clean up the code.

When you migrate to 2.0, you should get some warnings. The amount of warnings will depend on when you started using Devise. For recent applications, it should take 2 minutes to update (basically fixing up migrations and the locale file), older applications should be up to speed in 15-30 minutes. We have created a page with instructions to upgrade, be sure to read it for a smoother experience.

Finally, Devise 2.0 also includes:

  • Support to the reconfirmable feature. When on, if the user changes his e-mail, he needs to confirm the new e-mail address before the e-mail is finally updated;
  • We got rid of t.database_authenticatable and friends in migrations in favor of explicit code;
  • Better support to engines. For example, we now support config.parent_controller which you can set to something different from ApplicationController. There is a good sample engine here;
  • Rails 3.2 support. The previous Devise version (v1.5) runs fine but with a few deprecation warnings, v2.0 gets rid of them;

The CHANGELOG is available here.

Thanks everyone that contributed to this awesome release and, if you have any issues, please let us know in the issues tracker. Here to a better future!