Flowdock

Recent notes

RSS feed
May 20, 2009
0 thanks

Symbol Keys Only

While OpenStruct#new is rather indifferent to the kind of keys submitted, marshal_load requires Symbol keys only. Use of a string can cause difficulty.

To fix:

marshal_load(hash.inject({ }) { |h, (k,v)| h[k.to_sym] = v; h })

As a note, Rails has the Hash#symbolize_keys method that can be used in place.

May 19, 2009
0 thanks

Method functions like Hash#merge!

This method functions a lot like Hash#merge! only with a different name.

f = OpenStruct.new
# => #<OpenStruct>
f.marshal_load({:foo => 'bar'})
# => #<OpenStruct foo="bar">
f.foo
# => "bar"
May 19, 2009
2 thanks

Like JavaScript Object

For those familiar with JavaScript naked Objects, this is very similar.

May 19, 2009 - (v2.2.1 - v2.3.2)
2 thanks

How to set request parameters

On previous versions of TestRequest it was possible to set the request_parameters on the new action. This option is now gone, but it’s still possible to set the parameters after initialization.

Code example

request = ActionController::TestRequest.new
request.env["action_controller.request.request_parameters"] = { :foo => '42', :bar => '24' } 
May 15, 2009
0 thanks

script/generate can take table name

As far as I can tell script/generate will happily take the plural table name, at least in Rails 2.3.

May 13, 2009
3 thanks

Equivalent to Array#reject!

This method is functionally identical to Array#reject!

May 12, 2009
2 thanks

form_authenticity_token

Instead of disabling the CSRF check you can pass the authenticity_token field in your forms, eg:

<%= hidden_field_tag :authenticity_token, form_authenticity_token -%>
May 8, 2009
2 thanks

Using gmail SMTP server to send mail

If you’re running Rails >= 2.2.1 [RC2] and Ruby 1.8.7, you don’t need plugin below. Ruby 1.8.7 supports SMTP TLS and Rails 2.2.1 ships with an option to enable it if you’re running Ruby 1.8.7.

All You need to do is:

ActionMailer::Base.smtp_settings = {
  :enable_starttls_auto => true
}
May 7, 2009
0 thanks

RESTful actions

REST adds many constraints. It restricts your controllers to seven actions. Normally this is okay, but sometimes you need to add your own custom actions.

http://railscasts.com/episodes/35-custom-rest-actions

May 7, 2009 - (v2.2.1 - v2.3.2)
1 thank

Question

Can someone add some more information to this?

May 7, 2009
0 thanks

question?

Shouldn’t the second example be:

[1,2].zip(a,b)         #=> [[1, 4, 7], [2, 5, 8], [nil,6,9]]

??? or am I missing something?

May 7, 2009 - (v1_8_6_287 - v1_8_7_72)
0 thanks

Reg Ex Syntax

Is there any place where there is a full listing of RegEx syntax?

May 6, 2009 - (>= v2.3.2)
1 thank

Formatted route helpers are gone

In Rails >= 2.3 you can’t use formatted_xxx url helpers anymore.

However, you can still pass a :format option to url helpers, eg:

articles_path(:format => :csv) # => /articles.csv
May 4, 2009 - (v1_8_6_287)
2 thanks

NoMethodError: undefined method `each_char'

For some reason the each_char method on String is not available by default in Ruby 1.8.6 and you will be presented with a NoMethodError.

You can resolve this by requiring the jcode lib:

require 'jcode'
May 4, 2009
1 thank

clarification

Via Kenneth Kalmer:

From the man page: If salt is a character string starting with the characters “$id$” followed by a string terminated by “$”: $id$salt$encrypted then instead of using the DES machine, id identifies the encryption method used and this then determines how the rest of the password string is interpreted.

irb session

=>abNANd1rDfiNc”
irb(main):002:0>secret”.crypt(”abasasa”)
=>abNANd1rDfiNc”
irb(main):003:0>secret”.crypt(”$1$abasasa”)
=>$1$abasasa$2RZY2vd6E2ZEPSDa0eLec0″
irb(main):004:0>secret”.crypt(”$1$abasa”)
=>$1$abasa$ikoKICgwOFdcWgmDl9Asy1″

see http://www.opensourcery.co.za/2009/05/01/quick-nix-shadow-passwords-with-ruby/

May 2, 2009 - (v2.0.0 - v2.3.2)
0 thanks

Setting name and id for select_tag

Sometimes you need to use select_tag instead of select (because you’re after more control or need to use optgroups, for example), but still want the id/name conventions that select would give.

In this case, all you need to do is set the first parameter to whatever would be produced by select, and it’ll take care of the id and name attribute automatically, and thus ensure the form data is parsed correctly after submission.

For example, if you want to do something like:

form_for :comment do |f|
 f.select :article_id ...

which would give a select tag with id of “comment_article_id” and a name attribute of “comment[article_id]”, which be parsed into the params hash of:

'comment' => {'article_id' => ...

you can instead do

form_for :comment do |f|
 select_tag 'comment[article_id]' ...

which will give the same id and name attributes for the select tag and hence the same params hash in the controller

May 2, 2009
0 thanks

Re: Find random record

How about if you wanted to find a random set of records instead of a singular record, what would be the best way?

Thank you

May 2, 2009
8 thanks

Create a Hash from two Arrays

Here is my favorite idiom for creating a Hash from an Array of keys and an Array of values:

keys = [:a, :b]
values = [1,2]
h = Hash[*keys.zip(values).flatten]      # => {:b=>2, :a=>1}
May 2, 2009
3 thanks

Test if one array includes the elements of another

You can just use a set difference (aka minus) to see if one array includes all elements of another

not_included = [1,2,3] - (1..9).to_a
not_included      # => []

not_included = [1,2,3,'A'] - (1..9).to_a
not_included      # => ["A"]

Use intersection to test if any of the one are in the other:

shared = [1,2,3,'A'] & (1..9).to_a
shared     # => [1, 2, 3]
May 2, 2009
2 thanks

Re: Find random record

Ordering by RAND() is not a wise idea when you have a large table with lots of rows. Your database will have to calculate a different random value for every row in your database – O(N) – then sort the entire table by those values – O(N log N).

There are a number of better ways to get a random record from your table. Some examples:

  • If your table is not sparse, choose a random ID and get that row (or the nearest row):

rand_id = rand(Model.count)
rand_record = Model.first(:conditions => [ "id >= ?", rand_id]) # don't use OFFSET on MySQL; it's very slow
  • If your table is sparse, or does not have a primary key, consider adding an indexed column of random numbers between 0 and N. You can then order by this column quickly and choose a value using a method similar to the above example.

April 30, 2009
1 thank

Find random record

It’s as simple as:

Things.first(:order => 'RAND()')

Of course depending on your database it could be ‘RANDOM()’ or something similar.

April 30, 2009
1 thank

Caveat and design hints regarding :counter_cache

(From Obie Fernandez/ The Rails Way, ISBN 978-0321445612. Thanks Obie!)

This caveat:

The value of the counter cache column must be set to zero by default in the database! Otherwise the counter caching won’t work at all. It’s because the way that Rails implements the counter caching behavior is by adding a simple callback that goes directly to the database with an UPDATE command and increments the value of the counter.

And these tips:

If a significant percentage of your association collections will be empty at any given moment, you can optimize performance at the cost of some extra database storage by using counter caches liberally. The reason is that when the counter cache attribute is at zero, Rails won’t even try to query the database for the associated records!

If you’re not careful, and neglect to set a default value of 0 for the counter cache column on the database, or misspell the column name, the counter cache will still seem to work! There is a magic method on all classes with has_many associations called collection_count, just like the counter cache. It will return a correct count value if you don’t have a counter cache option set or the counter cache column value is null!

April 30, 2009
1 thank

For specific entries, use Dir.glob

When working with the contents of a directory it’s not uncommon to be interested in a specific subset of the entries present.

Dir.glob can be used to fetch entries by name and File.stat can be used to determine the type of file.

April 30, 2009
0 thanks

attachments and implicit multipart

There is a small gotcha - this caught me up for a while.

If you are using implicit multipart mime types by naming your template xxx.text.html.erb and xxx.text.plain.erb, you will need to change your template name back to the original xxx.erb.

If you use the implicit template name, your attachment will be the only thing in the body of the message - it will ignore your template.

See the “Multipart email” section of the ActionMailer.base documentation.

April 30, 2009
0 thanks

Video tutorial

If you want to get up to speed with Rails’ caching and haven’t seen it already, definitely check out this video series on Scaling Rails:

http://railslab.newrelic.com/scaling-rails

April 29, 2009 - (<= v2.3.2)
1 thank

Including instance methods to JSON output

Use :methods parameter to include ActiveRecord instance methods to JSON output. :only and :except uses DB columns only.

@events.to_json(:include => { 
                  :images => { 
                    :only => [], :methods => [:public_url] }})

In the previous example events have multiple images and only public_url instance method is included in the JSON output.

April 28, 2009
1 thank

Moved to ActiveSupport::Inflector

This isn’t gone, it’s just been moved to the ActiveSupport module namespace.

See: ActiveSupport::Inflector#pluralize

April 28, 2009
3 thanks

Tip: Define from_param(...) as Opposite

Often when defining a to_param method, it’s handy to introduce an opposite method for decoding them. For example:

class User < ActiveRecord::Base
  def self.from_param(param)
    find_by_name!(param)
  end

  def to_param
    name
  end
end

While you can just as easily redefine the find() method, this may be confusing since the expectation is that find() works with numerical IDs, or whatever the key column is defined as.

April 28, 2009 - (>= v2.3.2)
5 thanks

A very thorough explanation of use

Ryan Daigle has a great article about 2.3’s new nest forms which does a really good job of explaining how to use this and some of the potential gotchas. Highly recommended:

http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes

April 27, 2009 - (>= v2.0.0)
0 thanks

has_one through belongs_to not working

code example:

class Company < ActiveRecord::Base
  has_many :route_lists
end

class RouteList < ActiveRecord::Base
  belongs_to :company
  has_many :routes
end

class Route < ActiveRecord::Base
  belongs_to :route_list
  has_one :company :through => :route_list
end

This creates an invalid SQL query, where the keys in the join between route and routelist are switched, when used as an include:

Routes.find :all, :conditions => ["companies.type = ?", "Account"], :include => :company

route_lists.route_list_id = route.id

instead of: route_lists.id = route.route_list_id