Rails Kitchen

It's a place to write on stuff I learned recently.

Slide - an Introduction to Active Record Associations

| Comments

My second session to the new joinies in Ruby Software Pvt.Ltd. is on Active Record Associations. The primary goal of this session is to introduce the basic concepts of Active Record Associations.
The slides of my session is available below ..



Hope you enjoyed my slides.

Slide - an Introduction to Ruby on Rails

| Comments

In my current company Ruby Software Pvt.Ltd, I gave a session on Ruby on Rails to New joiners. The primary goal of this session to give an introduction about Ruby on Rails Framework and make them do a sample application from scratch. 
The slides of the session is available below..



Hope you enjoyed my slides.

Rspec Run Specific Set of Tests Using –tag Option

| Comments

In my current project I wanted to avoid running a few set of slow tests every time. Tagging feature in rspec allow us to filter the examples to be run by tag.

We can use the –tag (or -t) option to filter the examples by tags. The tag can be a simple name or a name:value pair. In the first case, examples with :name => true will be filtered. In the second case, examples with :name => value will be filtered, where value is always a string.

Tags can also be used to exclude examples by adding a ~ before the tag. For example ~tag will exclude all examples marked with :tag => true and ~tag:value will exclude all examples marked with :tag => value.

Given example show how to add tags to spec examples,
1
2
3
4
5
6
7
8
describe "group with tagged specs" do
  it "example I'm working now", :focus => true do; end
  it "special example with string", :type => 'special' do; end
  it "special example with symbol", :type => :special do; end
  it "slow example", :skip => true do; end
  it "ordinary example", :speed => 'slow' do; end
  it "untagged example" do; end
end
To run only examples with a simple tag, for examlple to run tests with a tag focus
run ”rspec spec/ –tag focus
Then the output should contain all the tests with tag :focus=>true
To exclude examples with a name:value tag
run ”rspec spec/ –tag ~speed:slow
Then the tests with tag speed:slow” will not be run.

Detailed documenation is given here

Thats it, Happy Testing….

Implement Dependent Select in Active Admin

| Comments

One of my prevois project, I needed to populate product catalogs in second select box depends on the product selected in first select box in active admin input form. I implemented this by refering one of the example by @abidsm in his github repo.

Implementation

First we need to add dependent_select.js file.
Now we need to add logic to catalogs_product.rb in admin folder.
catalogs_product.rb
1
2
3
4
5
6
7
8
9
ActiveAdmin.register CatalogsProduct do
  form do |f|
    f.inputs "Details" do
      f.input :product, :as => :select, :collection => Product.all.collect {|product| [product.name, product.id] }
      f.input :catalog, :as => :select, :input_html => {'data-option-dependent' => true, 'data-option-url' => '/products/:catalogs_product_product_id/catalogs', 'data-option-observed' => 'catalogs_product_product_id'}, :collection => (resource.product ? resource.product.category.catalogs.collect {|catalog| [catalog.attr_name, catalog.id]} : [])
    end
    f.actions
  end
end
Here ‘data-option-dependent’ => true will bind depentent select js to catalog input field.

‘data-option-observed’ => ‘catalogs_product_product_id’ specify that, the catalog field is depending on input in product field. catalogs_product_product_id is the id of the product field in this form.

Now we need to specify the json method which will populate catalogs data depends on the product is selected in parent input select.
‘data-option-url’ => ‘/products/:catalogs_product_product_id/catalogs’

Now we need to add index method with json output in catelogs controller.
catalogs_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
class CatalogsController < ApplicationController
  respond_to :json

  def index
    if params[:product_id]
      product = Product.find_by_id(params[:product_id])
      @catalogs = product.category.catalogs
    else
      @catalogs = Catalog.all
    end
    render :json => @catalogs.collect {|catalog| {:id => catalog.id, :name => catalog.attr_name} }
  end
end
routes.rb
1
2
3
4
5
6
DependentSelect::Application.routes.draw do
  root :to => 'pages#main'
  resources :products do
    resources :catalogs
  end
end
That’s it now you can see catalog select box will be repopulated when we select a product in product select box. This can be implemented in any of formastic input forms.

Ruby on Rails Applications Security Vulnerability Checking Tool - Brakeman

| Comments

Rails is one of the best frameworks to build websites, it solved a lot of security issues by default, like SQL injection and Cross-Site Scripting. Still there are lots of chances to have security vulnerabilities in our application.

Brakeman is a static analysis tool which checks Ruby on Rails applications for security vulnerabilities. Unlike many web security scanners, Brakeman looks at the source code of your application. This means you do not need to set up your whole application stack to use it. Once Brakeman scans the application code, it produces a report of all security issues it has found. Brakeman requires zero setups or configuration once it is installed, what you have to do is to just run it.
We can also integrate brakeman with Jenkins by adding Brakeman plugin. For continuous testing, We can use Guard::Brakeman, which allows you to automatically run Brakeman tests when files are modified.

Installation
Using RubyGems:
1
gem install brakeman
Using Bundler, add to development group in Gemfile and set to not be required automatically:
1
2
3
group :development do
 gem 'brakeman', :require => false
end
Running Brakeman
The simplest way to get started with Brakeman is to just run it with no options in the root directory of your Rails application:
1
2
cd your_rails_app/
brakeman
This will scan the application in the current directory and output a report to the command line.

Alternatively, you can supply a path as an option to Brakeman:
1
brakeman your_rails_app
To specify an output file for the results:
1
brakeman -o output_file
The output format is determined by the file extension or by using the -f option. Current options are: text, html, tabs, json, markdown, and csv.

Multiple output files can be specified:
1
brakeman -o output.html -o output.json
Example result : For more options and documentation, visit official site :

Translate Active Record Model Name, Attributes and Error Messages With Rails Internationalization (I18n) API

| Comments

The Ruby I18n gem which is shipped with Ruby on Rails provides an easy-to-use and extensible framework for translating your application to a single custom language other than English or for providing multi-language support in your application.

To translate model Project to another language (for example, to arabic), add model name in arabic with key one and pluralal of model name in arabic with key other in to config/locales/ar.yml.
1
2
3
4
5
6
7
8
9
10
11
12
13
ar:
  activerecord:
    models:
      project:
        one: مشروع
        other: مشاريع
      task:
  one: مهمة
        other: المهام   
    attributes:
      project: 
        title: لقب
        # will translate Project attribute "title" as "لقب"
that’s it, now if you switch your application to Arabic you can see everywhere in the project is translated into مشروع and projects is translate into مشاريع. Project attribute title will be translated into لقبs.

Active Record validation error messages can also be translated easily. Active Record gives you a couple of namespaces where you can place your message translations in order to provide different messages and translation for certain models, attributes, and/or validations.

Consider a Project model with a validation for the title attribute like this:
1
2
3
class Project < ActiveRecord::Base
  validates :title, presence: true
end
The key for the error message in this case is :blank. So add message to be shown in following order to ar.yml
1
2
3
4
5
6
7
activerecord:
    errors:
      models:
        project:
          attributes:
            title:
              blank : لا يمكن أن يكون البنك
For more details check official rails guides

Two Ways to Avoid Cross-origin Resource Sharing Issue in Development Environment

| Comments

When you are developing a Front End Application using Backbone.js, Angular.js or any other MV* frameworks or making an AJAX call, you might have faced the issue with Cross-origin resource sharing (CORS). You will face this issue if you are accessing the hosted web services (API) from your development environment because the domains are different.

We can solve the CORS issue in different ways. The best solution is to implement reverse proxy in the development environment. Here is a sample virtual host file which has reverse proxy implemented:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<VirtualHost *:80> 
    ServerName front_end_app.eshaiju-desktop.com 
    DocumentRoot /home/eshaiju/Projects/front_end_app/public 
    <Directory /home/eshaiju/Projects/front_end_app/public> 
       AllowOverride all    
       Options -MultiViews  
    </Directory> 
       
    LoadModule proxy_module modules/mod_proxy.so 
    ProxyRequests Off 
  
    <Proxy *> 
      Order deny,allow 
      Allow from all 
    </Proxy> 
  
    ProxyPass /api http://eshaiju.in/api 
    ProxyPassReverse /api http://eshaiju.in/api 
             
ErrorLog /var/log/apache2/error.log 
               
# Possible values include: debug, info, notice, warn, error, crit, 
# alert, emerg. 
LogLevel warn 
     
CustomLog /var/log/apache2/access.log combined 
</VirtualHost>
From your app if you start accessing the /api URL it will be accessed from the proxy URL.

There is anohter simple way to avoid this security check in developement environment. Disable cross-domain security check for AJAX call in Google Chrome for deveopment environment.
Start Google Chrome with no security from command line, OSX:
1
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --disable-web-security
Start Google Chrome from command line, Ubuntu/Linux:
1
google-chrome --disable-web-security
Start Chromium from command line, Ubuntu/Linux:
1
chromium-browser --disable-web-security
For Windows:
1 - Create a shortcut to Chrome on your desktop.
2 - Right-click on the shortcut and choose Properties, then switch to “Shortcut” tab. In the “Target” field, append the following: –args –disable-web-security.
3 - Restart Chrome

After this chrome will open with all securty disabled. So AJAX call will work without any problem.

ActiveSkin - Flat Skin for Active Admin

| Comments

Active Admin is a Ruby on Rails plugin for generating administration style interfaces. It abstracts common business application patterns to make it simple for developers to implement beautiful and elegant interfaces with very little effort.

Default interface of active admin:
We can customize the default style of active admin by over riding css values and and sass variables. ActiveSkin is a flat skin for active admin. We can even change basic colors of the theme by changing values of some variables.

Installation
Having active admin installed add the following line to your application’s Gemfile:
1
gem 'active_skin'
Now we need to include active skin css to our project.
Add following code to active_admin.css.scss
1
2
3
4
5
@import "active_admin/mixins";
@import "active_admin/base";
...
@import "active_skin";
...
Change logo by setting the $skinLogo variable above active_skin import line in active_admin.css.scss.
1
$skinLogo: url("admin_logo.png") no-repeat 0 0;
You can even change basic colors of the theme by placing some other variables:
1
2
3
4
5
$skinActiveColor: #001cee;
$skinHeaderBck: #002744;
$panelHeaderBck: #002744;

@import "active_skin";
Color examples

‘Standard’ for the Order of Associations, Scopes, Includes, Validations in a Rails Model

| Comments

Rails is all about ‘Convention over Configuration’. There are community-driven Ruby coding style guides. But there is no such convention of following a ‘standard’ for the order of arranging associations, scopes, includes, validations in a Rails Model. But we can create one for our project and be consistent with it in all the models. This is what I follow. Thanks to this stackoverflow post.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class Model < ActiveRecord::Base   
  #all mixins
  include Something
  extend Something

  #constants 
  MAX_LIMIT = 10

  #other stuff
  acts_as_taggable
  paginates
  attr_accessor :something 
  before_create :some_method

  searchable do
    text :something
  end

  #associations
  has_many :something
  belongs_to :something_else

  #validations
  validate_presence_of :something

  #scopes
  scope :something

  #instance methods
  def instance_method
  end

  #class methods
  def self.method
  end

  #private methods
  private
  def method2
  end
end

Check Test Coverage With SimpleCov Gem

| Comments

SimpleCov is a code coverage analysis tool for Ruby. It uses Ruby’s built-in Coverage library to gather code coverage data, but makes processing its results much easier by providing a clean API to filter, group, merge, format, and display those results, giving you a complete code coverage suite that can be set up with just a couple lines of code.

Getting started
Add SimpleCov to your Gemfile and bundle install:
1
gem 'simplecov', :require => false, :group => :test
Load and launch SimpleCov at the very top of your spec_helper.rb (or test/test_helper.rb, cucumber env.rb, or whatever your preferred test framework uses):
1
2
3
4
5
6
7
8
require 'simplecov'
  
Spork.each_run do
  if ENV['DRB']
    require 'simplecov'
    SimpleCov.start 'rails'  if ENV["COVERAGE"]
    end
end
Due to this code SimpleCov.start if ENV[“COVERAGE”] SimpleCov will only run if you execute your tests like this:
1
COVERAGE=true bundle exec rspec
Run your tests, open up coverage/index.html in your browser you can see detailed report on test coverage.