Notes posted to Ruby on Rails

RSS feed
December 12, 2014
0 thanks
November 27, 2014
1 thank

Adding index with other operator classes (PostgreSQL)

To perform on search by LIKE:

SQL Query:

SELECT users.* FROM users WHERE name LIKE 'Doug%';

Explain:

# Without index
Seq Scan on users  (cost=0.00..82183.32 rows=98524 width=418)
  Filter: ((name)::text ~~ 'Doug%'::text)

Adding index with operator class ‘varchar_pattern_ops’

add_index :users, :name, order: {name: :varchar_pattern_ops}
execute 'ANALYZE users;'

New Explain:

# With index
Bitmap Heap Scan on users  (cost=2444.46..56020.97 rows=98524 width=418)
  Filter: ((name)::text ~~ 'Doug%'::text)
  ->  Bitmap Index Scan on index_users_on_name  (cost=0.00..2419.83 rows=75940 width=0)
        Index Cond: ((name)::text ~>=~ 'Doug'::text)
November 24, 2014
1 thank

Arguments for .select must be array

Model.select(:field, :other_field, :and_one_more) has a typo. It must take an array of arguments as the description states:

Model.select([:field, :other_field, :and_one_more])

November 19, 2014
0 thanks

Also useful without respond_with

Using the class method #respond_to allows controller-level specification of the allowed mime-types. Without #respond_with , it enables a

Completed 406 Not Acceptable

response rather than

ActionView::MissingTemplate

error when an unsupported type is requested.

See: http://www.justinweiss.com/blog/2014/11/03/respond-to-without-all-the-pain/

November 19, 2014
1 thank

Bangladeshi Taka (BDT 1,200.95)

Code example

def to_bdt(amount)
  number_to_currency(amount, :unit => "BDT ", :separator => ".", :delimiter => ",")
end
November 17, 2014 - (>= v3.1.0)
0 thanks

Include items affected in output

If the result returned from the block is an Integer, the output will include a message about that number of “rows” in addition to the elapsed time.

say_with_time "Some complex, custom work" do
  counter = 0
  # ... do some stuff here that increments the counter ...
  counter
end

#=> "-- Some complex, custom work"
#=> "   -> 45.3725s"
#=> "   -> 52880 rows"
November 17, 2014 - (<= v4.0.2)
0 thanks

Include items affected in output

If the result returned from the block is an Integer, the output will include a message about that number of “rows” in addition to the elapsed time.

say_with_time "Some complex, custom work" do
  counter = 0
  # ... do some stuff here that increments the counter ...
  counter
end

#=> "-- Some complex, custom work"
#=> "   -> 45.3725s"
#=> "   -> 52880 rows"
November 14, 2014
3 thanks

Opposite of persisted?

So I can find it when I look next time.

November 14, 2014
1 thank

Opposite of #new_record?

So that next time I look I find it.

November 7, 2014 - (v1.0.0 - v4.0.2)
0 thanks

Non Layout Pages

A 404 error for the favicon will be thrown on pages where there is no layout if there isn’t a favicon in the public folder.

A situation would be when a controller method is used to render an image and the user chooses to open the image in a new tab bypassing the layout and the favicon_link_tag.

November 6, 2014
8 thanks

Find the First Instance in the Table. If None Exists, Create One.

Specify the data you’re looking for. If it exists in the table, the first instance will be returned. If not, then create is called.

If a block is provided, that block will be executed only if a new instance is being created. The block is NOT executed on an existing record.

Code example

MyStat.where(name: statistic_name).first_or_create do |statistic|
  statistic.value = calculate_percentage
  statistic.statistic_type = "percentage"
end
October 30, 2014 - (v3.0.0 - v3.2.13)
1 thank

Order with hash parameters only in ActiveRecord >= 4.0

If you use order with hash parameters on AR3 versions it wont work.

October 28, 2014
0 thanks

facing issue in create table (errno: 150)

I am trying to create table by writing the following code:

create_table :sam_server_user_audit do | t | t.column :user_id, :string, :limit => 100, :null => false t.column :user_type, :string, :limit => 20, :null => false t.column :status, :string, :limit => 20, :null => false t.column :created_at, :datetime, :null => false end

which generates:

CREATE TABLE `sam_server_user_audit` (`id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, `user_id` varchar(100) NOT NULL, `user_type` varchar(20) NOT NULL, `status` varchar(20) NOT NULL, `created_at` datetime NOT NULL, FOREIGN KEY (user_id) REFERENCES users (id)) ENGINE=InnoDB CHARACTER SET `utf8`

here It is adding a foreign key user_id automatically.

How can I avoid that?

October 28, 2014
2 thanks

Ordering on associations

For ordering on the attribute of an associated model you have to include it:

Package.includes(:package_size).order("package_sizes.sort_order")
October 1, 2014
0 thanks

Preselecting options

To preselect options, pass in the selected options in the options hash:

{ :selected => [ selected_option_1, selected__option_2, ... ] }

Code example

grouped_collection_select(:city, :country_id, @continents, :countries, :name, :id, :name, { :selected => [1, 5, 6 ] } )
September 18, 2014 - (<= v4.0.2)
0 thanks

Only in ApplicationController

Seems like we can use helper_method only in ApplicationController. Even if we will create child controller, methods that will be created in child and listed in child’s helper_method will not be accessible from the view.

For example, we have

class SystemController < ApplicationController
 def important_method
   "I am important!"
 end
end

and

class BookController < SystemController
 def index
 end
end

And calling important_method from Book’s index view will raise an NoMethodError.

September 12, 2014
0 thanks

Be careful with .select

With 999 people in the table:

Person.select('person.firstname').find_in_batches do |group|
  group.each { |person| puts person.firstname }
end

Will work properly.

But with 1001 people in the table, this will raise “Primary key not included in the custom select clause”. It’s a bit of a time bomb. If you’re writing tests for methods that use this, you won’t see a failure unless you’ve tested with more than records than the default batch size.

August 25, 2014 - (v3.1.0 - v3.2.13)
1 thank

This method does not correctly dup arrays

Watch out because this method does not correctly dup arrays values.

The bug can be reproduced with the following code:

hash = { 'a' => [1,2,3,4] }
dup  = hash.deep_dup
dup['a'].object_id == hash['a'].object_id # should return true

Rails 4 version does not have this issue because it is completely different implementation.

August 21, 2014 - (v4.0.2)
3 thanks

In Rails 4 it DOES return nil, even if the object you try from isn't nil

The try method does not raise a NoMethodError if you call a method that doesn’t exist on an object.

a = Article.new

a.try(:author) #=> #<Author ...>

nil.try(:doesnt_exist) #=> nil

a.try(:doesnt_exist) #=> nil

Note:

a.try(&:doesnt_exist) #=> Raises NoMethodError
August 19, 2014 - (v3.0.9 - v3.1.0)
0 thanks

False query string parameters removed

This method is used in url_for (therefore in redirects as well).

If you pass a query string parameter to a url route that is false, before Rails 3.1, the generate method would reject it.

This causes issues on the redirected page if you are depending on the param to be have a specific value.

In Rails 3.2 they remove params.reject! {|k,v| !v.to_param} altogether.

So every single param you send is a string.

August 19, 2014
0 thanks

callbacks

As a note, AFAICT, this skips “validations” but does still run all callbacks still [like after_save, etc.] So if you’re looking for something that just updates see here: http://stackoverflow.com/a/7243777/32453

August 13, 2014 - (>= v4.0.2)
0 thanks

Non-existent key semantics changed.

For Rails 4.0, the behaviour of this has changed when you pass a key that isn’t in the hash.

3.2 (undocumented):

{ a: 1, b: 2 }.extract!(:a, :x) # => {:a=>1, :x => nil}

4.0 (as per docs):

{ a: 1, b: 2 }.extract!(:a, :x) # => {:a=>1}

The 4.0 behaviour is now consistent with the behaviour of slice, the 3.2 behaviour was not.

August 8, 2014 - (>= v3.1.0)
0 thanks

Removed in Rails 3.1 and up

Use this instead

proxy_association.owner
August 8, 2014 - (v3.0.0 - v4.0.2)
0 thanks

Deprecated in favour of []

In Rails 3+

company.errors[:name]

In Rails 2.3 and below:

company.errors.on(:name)
August 5, 2014
0 thanks

Handling flash for ajax calls

This is helper method which can be easily used to handle flash for ajax calls

##call it in your js.erb
def flash_display
response = ""
flash.each do |name, msg|
	msg=msg+"<button type='button' class='close' title='hide' data- dismiss='alert'><i class='fa-times-circle-o fa pull-right'></i></button>".html_safe
  response = response + 
  content_tag(:div, msg, :id => "flash_# {name}",:class=>"alert alert-danger") do 
  	"#{msg}".html_safe  
  end 	
end
flash.discard
response
end

so in your controller,

def get_data_and_update_div
 @user_details=User.get_details
 if @user_details.nil?
   flash.now[:error]="Add your details and then submit"
   format.js { render   'shared/error_messages'}
 end

in error_messages.js.erb

$('#flash_messages').html("<%= escape_javascript raw(flash_display) %>");

in view file

<div id="flash_messages">
  <% if flash[:error] %>
   <%= content_tag :div, flash['value'], :id =>"flash_error" %>
 <% end %>
</div>
August 5, 2014
0 thanks

include respond_to in your controller action only if there are multiple formats of that view

consider this

def index
 @users=User.get_users
  respond_to do |format|
   format.html
   format.json
   format.js
  end
end

is good if you have a call to users/index by both

<%= link_to ("Show users",user_path)%>
##will render users/index.html.erb
===Also same call but with ajax
<%= link_to ("Show users",user_path,remote=>true)%>
 ##will render users/index.js.erb..handled by respond_to   block
===Also same call but with json
<%= link_to ("Show users",user_path,remote=>true,:format=>json)%>
##will render users/index.json.erb..handled by respond_to   block.

But if you have just first one,so remove respond_to block as you are sure that you only need index.html.erb ALWAYS

def index
  @users=User.get_users
end 

So if your action is being called both by BOTH ajax,non-ajax call,its good to use respond_to.

August 5, 2014
0 thanks

Using render to handle ajax call using same js.erb(DRY)

Suppose your application have many pages using some common view and is updated using ajax,so you can use a single js in multiple views to avoid duplication

format.js { render 'profile/show_user_details' }

And in my profiles/show_user_details.js i can use conditions instead of creating regular partials

<% if params[:controller]== "dashboard"%>
 $("admin_panel").show();
 $("user_panel").hide();
<% elsif params[:controller]== "user"%>
 $("admin_panel").hide();
 $("user_panel").show();
<% elsif params[:controller]== "video"%>
 $("admin_panel").hide();
 $("user_panel").hide();
 $("video_panel").show();
<% else %>
 $("admin_panel").hide();
 $("user_panel").hide();
 $("video_panel").hide();
<%end%>
August 5, 2014
0 thanks

simple use

Examples

<%= @user.created_at.to_date.to_formatted_s(:long_ordinal)%> => July 5th, 2014

OR

<%=@user.created_at.strftime("%b %d,%Y") %> =>  Jul 05,2014

quick ref:-

:db           # => 2008-12-25 14:35:05
:number       # => 20081225143505
:time         # => 14:35
:short        # => 25 Dec 14:35
:long         # => December 25, 2008 14:35
:long_ordinal # => December 25th, 2008 14:35
:rfc822       # => Thu, 25 Dec 2008 14:35:05 +0000