Jan 09

Cleaning up your helpers from html_safe with yield

Hi there,

First of all I would like to wish you a very happy new year.

Well it’s been a while I haven’t posted here and wondering if I should keep this blog or remove it.

In fact, I think I should post some tips and tricks about ruby and ruby on rails (aka ROR) from time to time.

So for the new year here is one of my tip.

Ruby / Rails Junior developers sometimes write codes that does not look to bad but still …

They might write something like this, some bunch of rails helpers with many html_safe in it. They do it good, because logic is extracted from view but not so good finally. The following of this post is a tip that may help you to refactor your code. Code improvement is better.

My goal here is to keep view stuffs like content_tag (except link_to) away from helpers and use them only in views.
But how do you handle logic thing you may ask, please use something you do not use very often in ruby: blocks and yield. Well to illustrate the point here is a simple example.

A simple helper to render links depending of the context (say we want to render a group menu like in google plus top menu bar)

# View
<%= render_groups_menu_links(account, user.groups) %>
# Helper
def render_groups_menu_links(account, groups)
  content_tag(:ul) do
    groups.map do |group|
      html_options = {}
      # do some logical stuffs here, for example selecting the current group and highlight the link
      # Well, you get the point. This is where view logic belongs to
      html_options[:class] = 'current' if page_matches_group_path?(group)
      content_tag(:li) do
        link_to group.name, account_group_path(account, group), html_options
      end
    end.join.html_safe
  end
end

Simple and fairly clean isn’t it?

Well I would not say so, IMHO

Here are some points that looks bad to me:

  1. Use of too many content_tag. Why not writing simple html tags?
  2. Use of html_safe. If you end up using it it is a code smell. You are likely doing something wrong. Of course there are cases when you need it but not here
  3. Views stuffs should not belong to helpers if possible. Think about helpers like number_with_delimiter or strip_tags or truncate … There are no reason you need to use simple content_tag here

So let rewrite it a bit:

# View
<ul>
  <%= render_groups_menu_links(account, account.groups) do |link| %>
    <li><%= link %></li>
  <% end %>
</ul>
# Helper
 
def render_groups_menu_links(account, account.groups)
  groups.each do |group|
    html_options = {}
    # do some logical stuffs here, for example selecting the current group and highlight the link
    # Well, you get the point. This is where view logic belongs to
    html_options[:class] = 'current' if page_matches_group_path?(group)
    yield link_to(group.name, group_path(group), html_options)
  end
  nil
end

Do not forget to return nil to your helpers unless you end up returning groups array wich will be appended to view

Jan 14

Reloading models in Rails 3.1 when usign Spork and cache_classes = true

Speeding up you tests with Spork is very common when developping Rails applications.

What Spork do is preloading your application in a server and copies a fork of that server whenever you run tests.

It avoids reloading all the rails stack !! That is great !!!

But the problem I ran into is that I wanted to be able to

  • reload my application files
  • and keep cache_classes = true

That is why I like ruby and rails (and great coders there ! ). What I simply did :

  1. Reading and understanding the rails initialize process  (especially these lines engine.rb and finisher.rb )
  2. Adding these small pieces of code in my prefork block with Spork trap method 
  3. trap eager loading in my prefork block like below
  require 'rails/application'
 
  # Use of https://github.com/sporkrb/spork/wiki/Spork.trap_method-Jujutsu
  Spork.trap_method(Rails::Application, :reload_routes!)
  Spork.trap_method(Rails::Application::RoutesReloader, :reload!)
 
  require 'rails/mongoid'
  Spork.trap_class_method(Rails::Mongoid, :load_models)
 
  # Prevent main application to eager_load in the prefork block (do not load files in autoload_paths)
  Spork.trap_method(Rails::Application, :eager_load!)
 
  # Below this line it is too late...
  require File.expand_path("../../config/environment", __FILE__)
  # Load all railties files
  Rails.application.railties.all { |r| r.eager_load! }

My own benefits : specs runs faster than setting cache_classes = false

You need small explanation of what I’ve done !

  Spork.trap_method(Rails::Application, :eager_load!)
  require File.expand_path("../../config/environment", __FILE__)
  Rails.application.railties.all { |r| r.eager_load! }

First, we prevent Rails::Application to loads files in the application autoload_paths such as app/models, app/controllers etc …

  Spork.trap_method(Rails::Application, :eager_load!)

Second, we load the rails stack :

  require File.expand_path("../../config/environment", __FILE__)

Last, we eager load all the engines :

  Rails.application.railties.all { |r| r.eager_load! }

Doing that we can make change in our models and avoid restarting spork.

Why don’t I just set cache_classes to false ?

Because the ActiveSupport::Dependencies.mechanism is set to :require and not :load

All application files are required and not just loaded (spork required them just after forking, not before).
This trick could resolve some inconsistencies in your application (such as already defined constant and else …)

Sep 27

Rubygems mini mirror

Hey all,

I just have published a new gem called rubygems-mini_mirror.

This is a small stuff that needs improvement on speed speaking but it works.
I will explain later on how it works because I have no time for that now.

Mar 17

Rspec 2.x and Fixtures

Hello,

It’s been a while when I last updated this blog. It seems that Rspec 2 can not use fixtures from Activerecord 2.3.x !

Impossible ? Not really, and thanks to ruby it was possible for me.

Let’s describe the background :

First of all, I had a gem built on jeweler that uses ActiveSupport::TestCase and ActiveRecord::Fixtures exactly implemented like in Rails
But one day, I decided to switch to RSpec (jeweler (1.5.2) uses as of my writing rspec ~> 2.3.0)

The conversion of test_* to “it” syntax was very quick and easy but loading fixtures was not !!!
So here is my implementation if you want to know how can this be possible :

# spec/spec_helper.rb
# .... some stuff ...
 require 'activerecord'
module  MyExtensions
  def self.extended(base)
    class << base # Beginning of Proxy
      def subclass_with_fixtures(*args,&block)
        child = subclass_without_fixtures(*args,&block)
        child.module_eval do
          include ActiveSupport::Callbacks
          define_callbacks :setup, :teardown
          include ActiveRecord::TestFixtures
 
          self.fixture_path = File.expand_path("../db/fixtures",__FILE__)
          self.use_instantiated_fixtures = false
          self.use_transactional_fixtures = true
          self.set_fixture_class :categories => 'Categorie'
 
          def run_in_transaction?
            true
          end
        end
        child
      end # End of method chain subclass_with_fixtures
      alias_method_chain :subclass, :fixtures
    end # End of Proxy
  end # End of extended
end # End of MyExtensions
 
RSpec::Core::ExampleGroup.extend(MyExtensions)
RSpec.configure do |config|
 
  config.after(:each) do
    run_callbacks :teardown, :enumerator => :reverse_each
  end
 
  config.before(:each) do
    run_callbacks :setup
  end
 
end

In my fixtures :

  # spec/db/fixtures/posts.yml
  a_post:
    title: "My first post"

Now when I want to load fixtures :

# spec/post_spec.rb
describe "Post" do
  before(:all) do
   self.class.fixtures :posts
  end
 
  it "should not save without a title" do
     post = posts(:a_post)
    post.title = nil
    post.save.should_not be_true
  end
end

Maybe, a better way can be found … if so please inform me !!!

Jan 12

HTTPClient and SSL verify certificate

If you as us in my company use self signed certificate and ran into an OpenSSL::SSL::SSLError when using httpclient gem.

Here is how to bypass ssl certificate verification :

The issue :

require 'rubygems'
require 'httpclient'
 
client = HTTPClient.new
url = "https://www.server1.com"
client.get(url)
at depth 1 - 19: self signed certificate in certificate chain
OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
	from /home/hery/.gem/ruby/1.8/gems/httpclient-2.1.5.2/lib/httpclient/session.rb:247:in `connect'
	from /home/hery/.gem/ruby/1.8/gems/httpclient-2.1.5.2/lib/httpclient/session.rb:247:in `ssl_connect'
	from /home/hery/.gem/ruby/1.8/gems/httpclient-2.1.5.2/lib/httpclient/session.rb:639:in `connect'
	from /home/hery/.gem/ruby/1.8/gems/httpclient-2.1.5.2/lib/httpclient/timeout.rb:128:in `timeout'
	from /home/hery/.gem/ruby/1.8/gems/httpclient-2.1.5.2/lib/httpclient/session.rb:631:in `connect'
	from /home/hery/.gem/ruby/1.8/gems/httpclient-2.1.5.2/lib/httpclient/session.rb:522:in `query'
	from /home/hery/.gem/ruby/1.8/gems/httpclient-2.1.5.2/lib/httpclient/session.rb:147:in `query'
	from /home/hery/.gem/ruby/1.8/gems/httpclient-2.1.5.2/lib/httpclient.rb:953:in `do_get_block'
	from /home/hery/.gem/ruby/1.8/gems/httpclient-2.1.5.2/lib/httpclient.rb:765:in `do_request'
	from /home/hery/.gem/ruby/1.8/gems/httpclient-2.1.5.2/lib/httpclient.rb:848:in `protect_keep_alive_disconnected'
	from /home/hery/.gem/ruby/1.8/gems/httpclient-2.1.5.2/lib/httpclient.rb:764:in `do_request'
	from /home/hery/.gem/ruby/1.8/gems/httpclient-2.1.5.2/lib/httpclient.rb:666:in `request'
	from /home/hery/.gem/ruby/1.8/gems/httpclient-2.1.5.2/lib/httpclient.rb:591:in `get'
	from (irb):5

Solution :

client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
client.get(url)

Nov 17

ActiveRecord like searching object in Rails form helpers

Ruby is a wonderful language. And Rails is a wonderful framework.
Why ? Because of Duck typing !!!

Example :

You build a database application for a book store

Books are classified by :

  • Genre
  • Author
  • Country

On a search page, you can search with a title text field, author select box, genre checkboxes.
So we want to create a search form with all the fields described above :

<%= form_tag('/search') do %>
  <p>
    <label for="title">title</label>
    <%= text_field_tag 'title' %>
  </p>
  <p>
    <label for="author">Author</label>
    <%= select_tag 'author',  options_for_select @authors, @selected_author %>
  </p>
  <% @genres.each do |g| %>
    <p>
      <label for="<%= 'genre_' + g.id.to_s %>"><%= g.label %></label>
      <%= check_box_tag 'genre[]', g.id, g.id == @selected_genre, :id => "genre_#{g.id}" %>
    </p>
  <% end %>
<% end %>

When I submit the code, it does not keep the value of the search fields, as it is when passing activerecord object in form helpers (with text_field not text_field_tag.)
Ok!! And what if I construct an object behaving like activerecord object ?
My template will be like this :

<%= form_for @search do |f| %>
  <p>
    <%= f.label :title, 'Title' %>
    <%= f.text_field :title %>
  </p>
  <p>
    <%= f.label :author, 'Author' %>
    <%= f.select :author, @authors %>
  </p>
 
  <% @genres.each do |g| %>
    <p>
      <label for="<%= 'genre_' + g.id.to_s %>"><%= g.label %></label>
      <%= check_box_tag 'search[genre][]', g.id, g.id == @selected_genre, :id => "genre_#{g.id}" %>
    </p>
  <% end %>
  <%= submit_tag "Search" %>
<% end %>

Yes we have a namespace called “search” on all parameters such as “search[title]” but I think it is not ugly, instead the code will be more readable !!!
Ok, but what’s the magic ? How can I have an activerecord like search object ?

Simply like that :

# encoding: utf-8
class Search
  def initialize(params={})
    @params = Hash.new.merge(params['search'] || {})
  end 
 
  def method_missing(method_sym,*args)
    case method_sym.to_s
    when /^\[\]=?$/
      @params.send(method_sym,*args)
    when /^(.*)=$/
      @params.update($1,*args)
    else
      @params[method_sym.to_s]
    end
  end
 
end

In your controller, simply instantiate a @search variable with your parameters :

# app/controllers/search_controller.rb
 
def search
  @search = Search.new(params)
  # ....
end

Oct 20

Ruby Rails : How to bypass skip validation in Devise

Since my last post with email validations, I was looking for a solution to integrate it with devise

Sadly for me, devise implements the old way of validating email with regexp :

# From devise gem version 1.1.3
validates_format_of     :email, :with  => email_regexp, :allow_blank => true

Well, as I don’t want to hack activemodel’s code, I prefer to skip the validates_format_of method in User class.

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable, :lockable and :timeoutable
  include SkipableMethod
 
  # Devise is great but uses the oldest way with regexp to validate email
  skip_and_restore_method(:validates_format_of) do
    devise :database_authenticatable, :registerable,
      :recoverable, :rememberable, :trackable, :validatable
  end
 
  # Replace with a validation of my own
  validates :email, :email => true, :presence => true
 
  # Setup accessible (or protected) attributes for your model
  attr_accessible :email, :password, :password_confirmation, :remember_me
 
end

And then the library :

module SkipableMethod
  module ClassMethods
 
    protected
    def __skip_method(*args);end
 
    def skip_and_restore_method(*method_names,&block)
      method_names.each do |method_name|
        instance_eval <<-EVAL
        alias #{method_name}_skipped #{method_name}
        alias #{method_name} __skip_method
        EVAL
      end
 
      yield
 
      method_names.each do |method_name|
        instance_eval <<-EVAL
        alias #{method_name} #{method_name}_skipped
        undef #{method_name}_skipped
        EVAL
      end
    end
  end
 
  def self.included(receiver)
    receiver.extend         ClassMethods
  end
end

TODO :

Some tests :D

Aug 19

Enumerable grep method in Ruby

There is some methods that are not very known among ruby developpers.
One of them is Enumerable#grep method.
I would like to share one of the use case I have to face with, and how I implement grep.

Purpose, I have a Hash representing a simple network
I’d like to select all the people related to :patrick with network label as key.

# Say I have this hash
h = {
  :work => { :patrick => [:joana, :elvis] },
  :football => { :patrick => [:john, :fred, :marcus] , :john => [:paul, :patrick]},
  :friends => { :paul => [ :joana, :elisabeth]}
}
# I want this result :
{
  :work => [:joana,:elvis],
  :football => [:john, :fred, :marcus]
}

A solution is to iterate throug each values then select :patrick

  h.inject({}) do |memo,(k,v)|
   if v.has_key?(:patrick)
    memo.merge(k => v[:patrick])
   else 
    memo
   end
  end

Though it works, I think this piece code is not “rubyesque”.

Well, this is a basic case but imagine you have to select X number of variables or more ( :patrick,:paul … etc ) or worse select with a more complex criteria.

After digging into the rdoc documentation, it seems that Enumerable#grep matches our requirements :

  • It takes a parameter to compare with each elements of the Enumerable
  • It can take a block that returns the value of matching elements

Well, how can we implement that ?
This code below demonstrate why I love Ruby !

class NetworkPattern
  def initialize(*args)
    @matches = args
  end
 
  def ===(pair)
     key, value = pair
     value.values_at(*@matches).any?
  end
 
  def result(hash)
    hash.values_at(*self).compact.flatten
  end
 
  def exec(hash)
    Hash[ hash.to_a.grep(self){|k,v|  [k,self.result(v)] } ]
  end
 
  def to_a
     @matches
  end
end
 
pattern = NetworkPattern.new(:patrick)
 
Hash[ h.to_a.grep(pattern){|k,v|  [k,pattern.result(v)] } ] 
=> { :work => [:joana, :elvis], :football=>[:john, :fred, :marcus]}
# With somer refactoring, we implement NetworPattern#exec and use it 
pattern.exec(h)
=> { :work => [:joana, :elvis], :football=>[:john, :fred, :marcus]}

Well it may seem more complicated but if you want to select both :patrick and :paul relationships, the code does not change howmany arguments you pass in NetworkPattern.new

pattern = NetworkPattern.new(:patrick, :paul)
pattern.exec(h)
=> { :work => [:joana, :elvis], :football =>[:john, :fred, :marcus], :friends =>[:joana, :elisabeth]}

All the logic belongs to the class NetworkPattern and it uses Enumerable#grep with block return.
In your project you can use something like that since it can be easily tested and more readable.

Jul 21

Email validation in Ruby On Rails 3 or Active model without regexp

In Rails 3.0, you can use custom validator in your active_record model.
So I wanted to manage email validations without regexp matching like others do.
I find a new way to make this work thanks to ruby mail gem, a dependency of Rails 3.0

I use this with devise, see my blogpost here : Ruby Rails : How to bypass skip validation in Devise

Edit : Here is a gem https://github.com/hallelujah/valid_email

class User < ActiveRecord::Base
  validates :email, :presence => true, :email => true
end

Just put a file in app/validators/email_validator.rb

require 'mail'
class EmailValidator < ActiveModel::EachValidator
  def validate_each(record,attribute,value)
    begin
      m = Mail::Address.new(value)
      # We must check that value contains a domain and that value is an email address
      r = m.domain && m.address == value
      t = m.__send__(:tree)
      # We need to dig into treetop
      # A valid domain must have dot_atom_text elements size > 1
      # user@localhost is excluded
      # treetop must respond to domain
      # We exclude valid email values like <user@localhost.com>
      # Hence we use m.__send__(tree).domain
      r &&= (t.domain.dot_atom_text.elements.size > 1)
    rescue Exception => e   
      r = false
    end
    record.errors[attribute] << (options[:message] || "is invalid") unless r
  end
end

No regexp !! And beautiful !!

Here is the version without activerecord

require 'rubygems'
require 'active_model'
require 'active_support/all'
require 'active_model/validations'
require 'mail'
class EmailValidator < ActiveModel::EachValidator
  def validate_each(record,attribute,value)
    begin
      m = Mail::Address.new(value)
      # We must check that value contains a domain and that value is an email address
      r = m.domain && m.address == value
      t = m.__send__(:tree)
      # We need to dig into treetop
      # A valid domain must have dot_atom_text elements size > 1
      # user@localhost is excluded
      # treetop must respond to domain
      # We exclude valid email values like <user@localhost.com>
      # Hence we use m.__send__(tree).domain
      r &&= (t.domain.dot_atom_text.elements.size > 1)
    rescue Exception => e
      r = false
    end
    record.errors[attribute] << (options[:message] || "is invalid") unless r
  end
end
 
class Person
  include ActiveModel::Validations
  attr_accessor :name, :email
 
  validates :name, :presence => true, :length => { :maximum => 100 }
  validates :email, :presence => true, :email => true
end

Jul 07

How to translate your column fields and values with gettext in ruby on rails

I am proud to have published my first useful ruby gem.
It is called gettext_column_mapping, you can check out the code in my github repository.
I already released it as a gem through gemcutter/rubygems

It is based upon Masao Mutoh (gettext and gettext_active_record) and Michael Grosser (fast_gettext and gettext_i18n_rails) works.

Thanks to them :)

History

In my company we need a mean to translate bad written fields/table name in our database. Why ? because our applications are internationalized and we need to have cleaner name than “libelle” (the french word standing for label) to send to translators.

We also have some “constants” name saved in our tables so we need to translate them.

Then started this library a year ago.

Formerly, it was a library that depends on Rails … But I decided that it ccould be nice if it reaches these requirements :

  • Use of Rubygem to spread it more easily
  • Must be Rails agnostic
  • Can use either mutoh’s gettext or grosser/fast_gettext
  • Can be implemented easily on rails 2.3.x and 3.0 or other ruby web framework
  • Can have some built-in configurable rake tasks

All is done!

But now I would like to improve this gems (API, tests, documentation, implementation) , so if someone who reads this post can help … I must remind you that this project is open source. Partly, it has been developped at work but I burnt most many hours of my sparetime than at work

TODO ?

  • other database implementation (only mysql for now)
  • ORM agnosticism ?
  • More testing
  • More documentation
  • Rails < 2.3 compatibility backward
  • … and so many

Try it and give me feedback

Older posts «