permalink

Model default values

When looking for the best way to make default values, I’ve found that you shouldn’t rely on the DB for these. So in order to integrate these on your Model, I usually follow the next best practive:

 class User
    after_initialize :init

    def init
      self.number ||= 0.0
    end
  end

This way it will initialize to 0.0 if the value is nil

permalink

Custom Validation (twitter bootstrap checkbox). Part 2

After creating the custom input on Part 1, we now needed to include a custom getter for each of these inputs. We could set up a method for each input inside our model but that wouldn’t be as cool, so we create a gem with the following behavior:

Object.instance_eval do 
   def check_for_check( *attrs )
       attrs.each do | attr |
           self.class_eval %Q{
                def #{attr}
                    #{attr}_check ? read_attribute(:#{attr}) : 0
                end
           }
       end
   end
end

This will make it so that we only have to add this to our model:

check_for_check :foo, :bar
permalink

Custom Input with Twitter Bootstrap

Using simple_form and Twitter’s bootstrap we can implement a custom input for the prepend left box used in bootstrap.

First you create an inputs folder under your app directory and then a file named left_box_input.rb with the following code:

class LeftBoxInput < SimpleForm::Inputs::Base
  def input
    "<div class='input-prepend'><span class='add-on'>#{options[:symbol]}</span>#{@builder.text_field(attribute_name, input_html_options)}</div>".html_safe
  end
end

Then in your views just call it the following way:
<%= f.input :foo, :as => :left_box, :symbol => "2 + 2 ?" %>
Then you will have in your views something like this:

permalink

Custom Validation (twitter bootstrap checkbox)

After jumping the wagon with Twitter Bootstrap for a new client app we are working on, I found myself in to some problem trying to implement this type of input:

We only have one input let’s say name and we wan’t to validate it’s presence when the check is true. The check is a virtual attribute named name_check. So using simple_form gem for this form.
We need to create the custom input element first, we do this by creating an inputs folder under the app folder. We name our file prepend_checkbox_input.rb

class PrependCheckboxInput < SimpleForm::Inputs::Base
  def input
    "<div class='input-prepend'>
<label class='add-on active' title='#{options[:tooltip]}' rel='tooltip' >
#{@builder.check_box(attribute_name.to_s + '_check')}
</label>
#{@builder.text_field(attribute_name, input_html_options)}
<span class='help-inline'>
#{options[:help]}
</span>
</div>".html_safe
  end
end

The input will include an option for tooltip, it will automatically append ‘_check’ to the name of the input to create the check box element, the text field with all the regular HTML options and a help line under it.
This will be how we call it under our views:
  <%= f.input :name, :as => :prepend_checkbox, :tooltip => "Has name?", :help => "Please insert your name" %>
Now we include validations, for custom validators we need implement this one under our initializers:
ActiveRecord::Base.class_eval do
  def self.validates_checkbox(*attrs)
    attrs.each do |attr_name|
    validates attr_name, :presence => true, :if => "#{attr_name.to_s + '_check'} == '1'" 
    end
  end
end

We user *attrs as our input so that we can declare our validations on a single line like so:
 validates_checkbox :name, :phone, :number

permalink

Rails 3.1 custom serialize

A new feature that really makes our lives easier is the custom serialize option. Let’s say that your DB requires that when you save a serializable attribute to be in a CSV form instead of the YAML default.

If this is the case then you could use the following

  class CommaSeparatedList
    def load(text)
      return unless text
      text.split(",")
    end

    def dump(text)
      text.join(",")
    end
  end


So after creating this class you just call it as a parameter in your serialize call

  serialize :names, CommaSeparatedList.new


In this way the next time you save to your DB your data will be stored in CSV form.

permalink

Rails 3.1 asset pipeline

When you’re trying out the new asset pipeline it might will be hard to debug any CSS/JS since it will all be compressed in to one file.

When you use the link/include tag remember to add the next parameter

stylesheet_link_tag :admin, :debug => Rails.env.development?
javascript_include_tag :admin, :debug => Rails.env.development?

This way it will only server the files separately when in development mode.

permalink

Installing Rails 3.1 —pre on OSX Lion

After trying several ways of doing

gem install rails --pre
and still getting errors, I found the following to do the trick
rvm gemset rails --pre
It will save you a couple of hours.

permalink

Paperclip Scopes

A nifty pair of scopes for when you’re working with attachments on Paperclip that are images or other type of content.

# For finding images as in Article.attachments.images 
scope :images, where("file_content_type LIKE ?", "image%")
# For finding other files Article.attachments.docs
scope :docs, where("file_content_type NOT LIKE ?", "image%")

permalink

New Stickers

We are getting new stickers for our friends and clients who want to put them in the laptops/cars/bathroom stalls.

Here is a preview, get them while they’re hot.

Sticker

permalink

My favorite Spec of the day

Here is the controller spec!

def notify
 	@user = User.find(params[:id])
 	if @user.is_expert?
		@topic.experts << @user
	end  @
	user.notify_about_topic!(@topic)
end

And the implementation

it 'should notify user and add to leader board if user is an expert' do  
	user = mock_model(User, :is_expert? => true)  
	topic = mock_model(Topic, :id => 1)  
	collection = mock('col')  
	collection.should_receive(:<<).with(user)  
	topic.should_receive(:experts).and_return(collection)  
	user.should_receive(:notify_about_topic!).with(topic)  
	User.should_receive(:find).with(1).and_return(user)  
	Topic.should_receive(:find).with(1).and_return(topic)  
	post :notify, :topic_id => topic.id, :id => 1, :format => 'js'  
	response.should be_succes  
	assigns(:user).should == user
end

Isn’t this nice to have completely decoupled specs from other outside logic, isn’t Rspec and TDD great?