RailsZilla is a Ruby on Rails blog for Tutorials, Tricks and Help

Contact me at LinkedIn  RailsZilla at Facebook  RailsZilla at twitter   google +1  Contact me at Xing  connect me at github

Ruby on Rails Database Indexes

Posted by Marcello on 22. September 2014 in Rails

Handy hint for better database performance in Ruby on Rails:

Always add DB index in your Migration!
By default, rails does not add indexes automatically for foreign key, you should add indexes by yourself.
If you want to speed up your performance, I suggest to add an index for

– foreign key
– columns that need to be sorted
– lookup fields
– and columns that are used in a GROUP BY.

This can improve the performance for sql query!

Let’s go on with our sample Migration for Databases. Go to your console / terminal and enter:

1
rails generate migration adding_columns_to_database

open the migration file in your editor / IDE and enter:

1
2
3
4
5
6
7
8
9
10
11
12
class CreateImages < ActiveRecord::Migration
  def self.up
    create_table "images" do |t|
      t.string :path
      t.integer :user_id
    end
  end

  def self.down
    drop_table "images"
  end
end

This would be the code if we would have used scaffold generator.
Rails does not add indexes automatically for foreign key, as you see.

This has to be added to our migration:

1
add_index :images, :user_id

Let’s have a look at our complete database migration:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class CreateImages < ActiveRecord::Migration
  def self.up
    create_table "images" do |t|
     t.string :path
     t.integer :user_id
    end

    add_index :images, :user_id
  end

  def self.down
    drop_table "images"
  end
end

However, there are a few cases which should not use indexes even in GROUP BY or lookup columns.
If you are using B-Tree indexes, you should not use them if the data has few distinct values (for example a male/female field). These can actually slow the query down.

For fields that are updated often, the overhead for recalculating the index with each addition/ update might not be worth the speed gained from having the index.

Tags: , , , , , ,

Generate polymorphic URL in Rails

Posted by Marcello on 5. August 2014 in Rails

In this example, I want to explain a best practice for Polymorphic URLs in Rails. I will show really bad things here as an illustrative example.
Don’t worry, we will refactor the code later ;-)

Let us assume that we have three models, Post, News and Comment. In most cases, a post has many comments and a news has many comments. They are defined like:

1
2
3
4
5
6
7
8
9
class Post < ActiveRecord::Base
  has_many :comments
end
class News < ActiveRecord::Base
  has_many :comments
end
class Comment < ActiveRecord::Base
  belongs_to :commentable, :polymorphic => true
end

Now we open our routes.rb file and we define the routes like:

1
2
3
4
5
6
resources :posts do
  resources :comments
end
resources :news do
  resources :comments
end

How are you mostly generate the url for posts’ comments and news’ comments? Many people write this to get the url for post-comments and news-comments:

Bad example …

1
2
3
4
5
6
# parent may be a post or a news
if Post === parent
  post_comments_path(parent)
elsif News === parent
  news_comments_path(parent)
end

This could get the URL for post and news:

1
2
3
4
5
if Post === parent
  post_path(parent)
elsif News === parent
  news_path(parent)
end

Let’s Refactor the code
Rails provides a simple way to generate the polymorphic url.
So we can use the polymorphic_path to get the url for post comments and news comments.

1
2
#"/posts/1/comments" or "'news/1/comments"
polymorphic_path([parent, Comment])

To get the url for post and news

1
2
#"http://example.com/posts/1/comments" or #"http://example.com/news/1/comments"
polymorphic_path(parent)

Lession learned:
polymorphic_path makes polymorphic url generation much easier and simpler. There is also a method named polymorphic_url which is the same as the polymorphic_path, except that polymorphic_url generate the full url including the host name.

Besides these, rails also provides the new and edit action for polymorphic_path/polymorphic_url

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
###
# we do a rake routes in our console
###

# "/posts/new"
new_polymorphic_url(Post)

# "http://example.com/posts/new"
new_polymorphic_path(Post)        

# "/posts/1/edit"
edit_polymorphic_path(post)    

# "http://example.com/posts/1/edit"
edit_polymorphic_url(post)

Tags: , , ,

Projekt Euler – probem 4 in Ruby

Posted by Marcello on 25. March 2014 in Ruby

Let’s go on with part four of our mathematical soultions-series in Project Euler:

Problem: The Largest palindrome product

A palindromic number reads the same both ways.
The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
Find the largest palindrome made from the product of two 3-digit numbers.

We first need a palindrome method. Let’s define it like this:

1
2
3
4
5
6
7
def palindrome? x
  # convert into String
  y = x.to_s
  # define look as the length of "y" divided by 2
  look = y.length / 2
  y[0..(look-1)] == y[-look..-1].reverse
end

We now need a method if it is divideable.

1
2
3
4
5
6
def divideable? x
  # because 999 ist the biggest number with three digits,
  # we count it down to the smallest which is 100
  999.downto(100).each { |y| return true if x % y == 0 && (x / y).to_s.length == 3 }
  false
end

Now we can piece together our puzzle:

1
2
3
4
5
6
7
8
9
10
# we count down from the largest six digit number which could be possible
# as a result of two three digit numbers multiplied
999999.downto(100000).each do |y|
  # now use the palindrome method and our divided method as condition
  if palindrome?(y) && divideable?(y)
    # print the result out
    puts "The result is #{y}"
    break
  end
end

This was easy to understand and hopefully gave you an inspiration how to deal with mathematical problems in Ruby.
Have a great day

Tags: , ,

ActiveAdmin with http authentication

Posted by Marcello on 4. February 2014 in Rails

Ever asked yourself how to use HTTP Basic authentication with ActiveAdmin?
There are several reasons to use HTTP Basic authentication for your backend. I needed a solution which can be recycled wherever I need a HTTP Basic authentication. I only wanted a central place for User and Password and I wanted just one call wherever I need my authentication.
Lets go …

In your application controller:

1
2
3
4
5
6
7
8
9
#
# app/controllers/application_controller.rb
#
  protected
  def authenticate
    authenticate_or_request_with_http_basic do |username, password|
      username == "admin" && password == "superpassword"
    end
  end

Now you can call …

1
before_filter :authenticate

… whenever you need a HTTP Basic authentication.

In case of ActiveAdmin, let’s call our before_filter like that:

1
2
3
4
5
6
7
8
9
10
#
# config/initializers/active_admin.rb
#
ActiveAdmin.setup do |config|
  ...

  # http auth for admin area
  config.before_filter :authenticate

  ...

Have fun!

Tags: , , , , , ,

Why the Rails default_scope is a bad thing

Posted by Marcello on 20. November 2013 in Rails

Activerecord provides default_scope to set a default scope for all operations on the model. I was never a friend of using default_scope, even when many friends used it in their projects. At the first look, it looks convenient but will lead to a headache very soon. We should avoid using it and here is why:

Assume we defined a default_scope in Comment model

1
2
3
class Comment
  default_scope where(published: true).order("created_at desc")
end

In this case the default_scope added some behaviors that we don’t recognize at the first look. The bad news: You can’t override default_scope by default! It lists comments order by created_at. Let’s have a look

1
2
> Comment.limit(10)
  Comment Load (3.3ms)  SELECT `comments`.* FROM `comments` WHERE `comments`.`published` = 1 ORDER BY created_at desc LIMIT 10

Continue with Why the Rails default_scope is a bad thing »

Tags: ,

Ruby on Rails Security Checklist

Posted by Marcello on 31. October 2013 in Rails

When ever we create a project, the same issue is our pain in the ass …
I talk about Security which is somehow dull and seems to be boring. I have done a simple checklist for a quick review of your code, which is divided in three simple steps: model, view and of course controller.

Our quick security checklist for your models

Use the helper method

1
attr_accessible

or

1
attr_protected

if you have to explicitly identify attributes that are accessible by the actions “create” and “update_attributes”. Don’t ever think that someone won’t try to post a value to your form.

Another thing to be aware is, when we use

1
attr_accessible

instead of

1
attr_protected

in this case we have the the advantage that it fails if new fields are added to a model. In this case you have to expose new fields explicitly. The method attr_accessible specifies a white list of model attributes that can be set via mass-assignment.
Continue with Ruby on Rails Security Checklist »

Tags: , , ,

Prime in Ruby – alternative solution

Posted by Marcello on 17. September 2013 in Ruby

As I showed in my article here, we can have another way of doing this job:

1
2
3
4
5
6
7
require 'prime'
goal = 600851475143

Prime.each(goal) do |number|
   @container = [number]
end
puts @container.last

This small piece of code illustrates togeter with my other solutions, that we have a vast amount of ways doing things in Ruby …

Tags: , , ,

Rails Security – Clickjacking

Posted by Marcello on 2. September 2013 in Rails

Note: This exploit is fixed in Rails 4

Our exploit today is clickjacking which is also called “UI redress attacks”. With clickjacking you can take an unexpected action for your victim by rendering the target site in an invisible frame.
As an example, an attacker may trick users into taking undesired actions like making a one-click purchase, following someone on Twitter, or changing their privacy settings and so on.

What can we do?
Our defence against clickjacking attacks can be done by preventing our site from being rendered in a frame or iframe on sites, that is not in our control.

The thing is that unlike older browsers, which required ugly “frame busting” JavaScripts, modern browsers support the X-Frame-Options HTTP.
The X-Frame-Options HTTP header instructs the browser about whether or not it should allow the site to be framed.
So we have to take care to include this HEADER.

If you’re on Rails 3:
Use the secure_headers RubyGem from Twitter to add an X-Frame-Options header. The value should be SAMEORIGIN or DENY

By default Rails 4 sends the X-Frame-Options header with the value of SAMEORIGIN

1
X-Frame-Options: SAMEORIGIN

With that Option, we tell the browser that our application can only be framed by pages originating from the same domain.

Tags: , , , ,

Security issue – symbol DoS vulnerability in ActiveRecord

Posted by Marcello on 29. August 2013 in Rails

There is a symbol DoS vulnerability in Active Record.

When a hash is provided as the find value for a query, the keys of the hash may be converted to symbols.

Have a look at this example:

1
User.where(:name => { 'foo' => 'bar' })

When you write this small piece of code, the string ‘foo’ would be converted into a symbol.
Impacted code would look something like this:

1
User.where(:name => params[:name])

If you know the tricks, you can coerce `params[:name]` to return a hash ;-)
When it returns a hash, the keys to that hash could be converted to symbols.
You should either upgrade ActiveRecord or use a workaround like this:

1
2
# this is really bad ...
User.where(:name => params[:name])

Change the code to this:

1
2
# this is a small workaournd
User.where(:name => params[:name].to_s)

Tags: , , ,

Favourite excuse

Posted by Marcello on 18. June 2013 in coffee break

New word of the day:

My code did not fail!
I just found another method that will not solve this problem …

Tags:

Copyright © 2011-2014  - RailsZilla – Ruby on Rails tutorials, tips and tricks All rights reserved. | Imprint | Privacy