Flowdock

Notes posted to Ruby on Rails

RSS feed
March 30, 2015
0 thanks

Passing a block does not behave as expected

When the condition is true, the block is not rendered:

<%= link_to_if true, users_path, {}, {} do %>
  <i class='fa fa-star'></i>
<% end %>

renders:

<a href="/users">/users</a>

But if the condition is false, the block will render:

<%= link_to_if false, users_path, {}, {} do %>
  <i class='fa fa-star'></i>
<% end %>

renders:

<i class='fa fa-star'></i>
March 30, 2015
0 thanks

If condition is false, options hash is ignored

Here, the class will be ignored:

<%= link_to_if false, 'Home', root_path, class: 'link' %> 
#=> Home
March 26, 2015
0 thanks

Save yourself a little typing

We often have a form with a select box that selects a model association. So for example to select a colour, when there is an associated Colour model, a select box will typically select :colour_id.

In this case, ActionView automatically humanizes :colour_id to produce “Colour” as the label text.

March 19, 2015
0 thanks

Wrong number of arguments (2 for 1)

If you get this error, wrap brackets with parentheses: Post.find_by_sql([“some query”])

March 19, 2015 - (v4.0.2)
0 thanks

number_field tag does not accept the same options as text_field_tag

number_field_tag does not accept the size or maxlength options; the max option for number_field_tag is used to control the size of the field. According to W3 http://www.w3.org/TR/html-markup/input.number.html , placeholder should be accepted, but I don’t find that this works in the way it works for text_field_tag.

March 18, 2015
0 thanks

Transactions and Stale ORM Data

Consider the following:

foo = Foo.new
bar = Bar.new

ActiveRecord::Base.transaction do
  foo.save! # succeeds
  bar.save! # failure, validation problem
end

foo.persisted? # true (!)

foo was not permanently stored in the database, but it was transiently saved, and this is reflected in the ActiveRecord model still in memory. But if you try

foo.reload # raises ActiveRecord::RecordNotFound

Don’t let stale data confuse you after using transactions!

Edited to add: This particular example does not succeed in reproducing the issue I encountered, which involved a slightly more complicated set of nested transactions. I haven’t managed to produce a simple test case where stale data remains in the model, but I have definitely experienced it in my app.

March 18, 2015
0 thanks

Transactions and Stale ORM Data

Consider the following:

ActiveRecord::Base.transaction do
  foo = Foo.new
  foo.save # succeeds

  bar = Bar.new
  bar.save # failure, validation problem
end
March 17, 2015 - (v2.1.0 - v3.2.13)
0 thanks
February 18, 2015
0 thanks

Not only for strings, but arrays and hashes too

exclude? is defined as !include?, meaning it is the exact opposite of include? . See the source.

This means that it works for Arrays and Hashes too, as well as for Strings.

It works for Arrays:

>> [nil].exclude?(nil)
=> false
>> [nil].include?(nil)
=> true
>> ["lala"].include?(nil)
=> false
>> ["lala"].exclude?(nil)
=> true

And for Hashes:

>> params = {}
=> {}
>> params[:db] = "lol"
=> "lol"
>> params.exclude?(:db)
=> false
>> params.include?(:db)
=> true
>> 
February 12, 2015
0 thanks

reorder

adding to stevo’s comment that reorder is also usefull when you have default scope in your model. eg: default_scope -> { order(created_at: :desc) }

February 11, 2015
0 thanks

Redirect to subdomain

If you’re looking to redirect to a subdomain you can do things like this:

redirect_to users_url(1, params: {a: :b}, subdomain: 'bob')
February 11, 2015
0 thanks

Why is this deprecated?

Anyone knows?

February 8, 2015
0 thanks

prepend_before_filter

If you need the method to be called at *the beginning* of the before_filter chain then you should use:

prepend_before_filter

February 3, 2015
0 thanks

Poor man's maybe

After creating a simple Maybe monad in Ruby, a colleaque noticed I could have just used try (I wasn’t aware try supports blocks). I think the method was even meant for such cases.

Why I mention this? Because it clarifies the whole ‘raises exception if method does not exist’ thing. It should not be crappy solution to exception handling, but allow for doing away with messy if statements. An example:

report = params[:query_type]
.try { |qt| build_query(qt) }
.try { |sql| run_query(sql) }
.try { |res| format_result(res) }

If any of the expressions params[], build_query, run_query etc. returns nil, the chain is halted and nil is returned. It still throws exceptions if a values is not nil and method does not exist, which is just like it should.

February 2, 2015
0 thanks

Be careful with cycles

This simplistic implementation (unlike Marshal.load(Marshal.dump(object)) doesn’t handle cycles in objects.

a = {}
b = {a: a}
a[:b] = b
a.deep_dup # SystemStackError: stack level too deep
January 16, 2015
0 thanks

An article about token-based authentication

www.codeschool.com/blog/2014/02/03/token-based-authentication-rails/

January 14, 2015
0 thanks

Have submit_tag send value as a nested resource

To have the submit_tag send it’s value within a nested resource for strong params use the name paramter.

submit_tag("Send", name: 'article[submit]')
January 8, 2015 - (v4.1.8)
1 thank

Text improvement

Where it says: without loading a bunch of records should say: without loading a bunch of columns/attributes Considering that record usually is a row.

January 5, 2015
0 thanks

SQL Injection?

Note that the version of leente and timdorr are probably vulnerable to SQL Injection (through attribute param).

Probably you want to look into with_lock instead of handcrafting SQL.

January 5, 2015
0 thanks

arguments do not need to be an array

it’s a small point, but if you look at the source, the method is defined with the splat operator in the arguments:

def select (*fields)

this means that a list of arguments is automatically converted to an array. There is no typo in the description above.

It will also work to pass an array:

select([:field1, :field2])

although the select method interprets this as a single argument, and places it into an array (due to the splat operator), this is then passed to the _select(*fields) method, which immediately calls fields.flatten!

So either a list or an array may be passed, both will work.

January 2, 2015
0 thanks

How safe is this?

Could this be used against a user supplied fragment like in a url route ?

December 29, 2014 - (<= v3.0.9)
0 thanks
December 16, 2014
1 thank

Group method chain

The group_method parameter can be a string representing a method chain:

grouped_collection_select(:city, :country_id, @continents, 'countries.sort.reverse', :name, :id, :name)

If we were to modify the Country model so we can sort by name:

class Country
  include Comparable

  def <=>(other)
    self.name <=> other.name
  end
end

The above example would have given us the countries sorted by name in descending sequence.

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 - (v2.0.0 - 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"