Flowdock

Recent notes

RSS feed
February 17, 2009
4 thanks

Date_select with assert_valid_keys

If you are using date_select with assert_valid_keys you have to allow 3 parameters named field(1i), field(2i) and field(3i).

For example with field

date_select("post", "written_on")

You have to allow following fields:

params[:post].assert_valid_keys( 
  'written_on(1i)', 'written_on(2i)', 'written_on(3i)'
)
February 17, 2009
7 thanks

Usage examples

Basic usage:

User.should_receive(:find).with(:all, anything).and_return("hello world")

Now:

User.find(:all, :conditions => "foo")  #=> "hello world"

But you can also use blocks for more complex matching logic. For example:

User.should_receive(:find) { |*args|
  if args.size == 2
    "received two arguments"
  else
    "something else"
  end
}.at_least(:once)

Now:

User.find(:all, :conditions => "bar")  #=> "received two arguments"
User.find(5)                           #=> "something else"

Of course normally you’d return mocks instead of strings.

February 17, 2009
9 thanks

Empty elements

If you want to output an empty element (self-closed) like “br”, “img” or “input”, use the tag method instead.

February 17, 2009
2 thanks

Remember to sanitize name

While useful when in need of richer markup inside a link, the name parameter isn’t sanitized or escaped and thus should be escaped when its content can’t be guaranteed to be safe.

E.g.

link_to(url, url)

may cause problems with character entities if url contains ampersands.

Correct usage
link_to(h(url), url)

This applies to all dynamic content.

February 17, 2009
2 thanks

See column

See the end part of the docs on column for example uses.

February 16, 2009
1 thank

See max

See max for comments and more usage examples.

February 16, 2009
2 thanks

Capping values

This method is very useful when you want to cap values:

# minimum ≤ value 
value = [input.to_i, minimum].max

# value ≤ maximum
value = [input.to_i, maximum].min

# minimum ≤ value ≤ maximum
value = [ [input.to_i, minimum].max, maximum ].min

# Practical example: Make sure destination is within container
destination.x = [ [current.x + current.velocity.x, 0].max, container.width  ].min
destination.y = [ [current.y + current.velocity.y, 0].max, container.height ].min
February 16, 2009
6 thanks

Usage example

Some examples:

# Remove even numbers
(1..30).reject { |n| n % 2 == 0 }
# => [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29]

# Remove years dividable with 4 (this is *not* the full leap years rule)
(1950..2000).reject { |y| y % 4 != 0 }
# => [1952, 1956, 1960, 1964, 1968, 1972, 1976, 1980, 1984, 1988, 1992, 1996, 2000]

# Remove users with karma below arithmetic mean
total = users.inject(0) { |total, user| total += user.karma }
mean = total / users.size
good_users = users.reject { |u| u.karma < mean }
February 16, 2009
1 thank

Reverse of this

If you want to do the reverse of this, e.g. go from a specific date and back to a certain day of the previous week, you can implement it like this:

def last_week(day = :monday)
  days_into_week = { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6}
  result = (self - 7).beginning_of_week + days_into_week[day]
  self.acts_like?(:time) ? result.change(:hour => 0) : result
end

If you do not want to make your own method of this, but just want to do it in a regular chaining of date methods (like Date.today.next_year.at_midnight), you can do it like the following:

(date - 7).next_week(:tuesday) # Tuesday, last week

Please note that you just need to subtract 7 if you want to move back a week. Only use these methods if you want to go to a specific day of the week.

February 16, 2009
1 thank

Reverse naming

The reverse of this is last_month and not previous_month, like one might believe from the naming.

February 16, 2009
1 thank

Reverse naming

The reverse of this is last_year and not previous_year, like one might believe from the naming.

February 15, 2009
0 thanks

use #collect instead of #each

The earlier reminder to use #collect instead of #each applies regardless of whether the tag is nested or not.

This is counterintuitive, as #collect returns an array of strings of HTML tags, but ActionView renders it properly.

February 14, 2009
1 thank

Clear and simple rescue

noxyu3m, your code is rescuing all exceptions, not just ActiveRecord::RecordInvalid.

I think this syntax is a bit more clear than using the global variable.

def create
  @model = Model.new(params[:model)
  @model.save!
rescue => err                          # rescues all exceptions
  logger.error(err.to_s)
end
February 14, 2009
0 thanks

Simple rescue

Take it easy:

def create
  @model = Model.new(params[:model)
  @model.save!
rescue
  logger.error(!$.to_s)
end

Global variable !$ refers to the Exception object.

February 13, 2009
1 thank

throws exception

when use use Model.find([1,2,3,4])

throws exception if no record exists with any of this ID

February 13, 2009
3 thanks

New test syntax

You can use either one and even mix in the same test case if you want:

class Test < Test::Unit::TestCase
  # old way to define a test method (prefix with test_)
  def test_should_be_valid_without_content
    assert Comment.new.valid?
  end

  # new way to define a test
  test "should be valid without content" do
    assert Comment.new.valid?
  end
end
February 12, 2009
4 thanks

Real life use

If you’re wondering what the base64 format is used for, here are some examples:

Just note that the encoded (character) data is about 30% larger than un-encoded (binary) data.

February 12, 2009
0 thanks

using collection=objects

It will fire one insert query per new record

February 12, 2009
4 thanks

Binary files

Another real important flag is b when dealing with binary files. For example to download an mp3 from the internet you need to pass the b flag or the data will be screwed up:

# Downloads a binary file from the internet
require 'open-uri'
url = "http://fubar/song.mp3"
open(url, 'rb') do |mp3|
  File.open("local.mp3", 'wb') do |file|
    file.write(mp3.read)
  end
end

Don’t say you haven’t been warned. :)

February 12, 2009
3 thanks

Other regular-expression modifiers

Likewise you can set Regexp::IGNORECASE directly on the regexp with the literal syntax:

/first/i
# This will match "first", "First" and even "fiRSt"

Even more modifiers

  • o – Perform #{} interpolations only once, the first time the regexp literal is evaluated.

  • x – Ignores whitespace and allows comments in * regular expressions

  • u, e, s, n – Interpret the regexp as Unicode (UTF-8), EUC, SJIS, or ASCII. If none of these modifiers is specified, the regular expression is assumed to use the source encoding.

Literal to the rescue

Like string literals delimited with %Q, Ruby allows you to begin your regular expressions with %r followed by a delimiter of your choice.

This is useful when the pattern you are describing contains a lot of forward slash characters that you don’t want to escape:

%Q(http://)
# This will match "http://"
February 12, 2009
4 thanks

Literal syntax

As you propably know you can create an Array either with the constructor or the literal syntax:

Array.new == []
# => true

But there is also another nice and concise literal syntax for creating Arrays of Strings:

["one", "two", "three"] == %w[one two three]
# => true

You can use any kind of parenthesis you like after the %w, either (), [] or {}. I prefer the square brackets because it looks more like an array.

February 12, 2009
2 thanks

Use this!

You should raise your own ArgumentError in methods to notify users of your class, if you think certain kinds of arguments aren’t acceptable.

def transfer_money(amount)
  unless amount.is_a?(Number)
    raise ArgumentError.new("Only numbers are allowed")
  end
  # ... Do the actual work
end
February 12, 2009
4 thanks

Useful scenario

This can be quite useful, for example when writing a command line script which takes a number of options.

Example

Let’s say you want to make a script that can make the basic CRUD operations. So want to be able to call it like this from the command line:

> my_script create
> my_script delete

The following script allows you to use any abbreviated command as long as it is unambiguous.

# my_script.rb
require 'abbrev'

command = ARGV.first
actions = %w[create read update delete]
mappings = Abbrev::abbrev(actions)
puts mappings[command]

That means you can call it like this:

> my_script cr
> my_script d

And it will print:

create
delete
February 10, 2009
8 thanks

Security issue with non-HTML formats

Please note that using default to_xml or to_json methods can lead to security holes, as these method expose all attributes of your model by default, including salt, crypted_password, permissions, status or whatever you might have.

You might want to override these methods in your models, e.g.:

def to_xml
  super( :only => [ :login, :first_name, :last_name ] )
end

Or consider not using responds_to at all, if you only want to provide HTML.

February 10, 2009
0 thanks

Cheat Sheet

I have written a short introduction and a colorful cheat sheet for Perl Compatible Regular Expressions (PCRE) as used by Ruby’s Regexp class:

http://www.bitcetera.com/en/techblog/2008/04/01/regex-in-a-nutshell/

February 10, 2009
0 thanks

Cheat Sheet

I have written a short introduction and a colorful cheat sheet for Perl Compatible Regular Expressions (PCRE) as used by Ruby’s Regexp class:

http://www.bitcetera.com/en/techblog/2008/04/01/regex-in-a-nutshell/

February 10, 2009
3 thanks

Cheat Sheet

I have written a short introduction and a colorful cheat sheet for Perl Compatible Regular Expressions (PCRE) as used by Ruby’s Regexp class:

http://www.bitcetera.com/en/techblog/2008/04/01/regex-in-a-nutshell/

February 10, 2009
2 thanks