Flowdock

Notes posted to Ruby on Rails

RSS feed
November 30, 2009
0 thanks

You can specify the format as well

You can also specify the format (in case you need to redirect a request coming in one format to another format):

redirect_to :action => 'show', :format => 'html'
November 26, 2009
0 thanks

How to check if a Yield has content?

How do I do this without actually calling the yield?

- if yield :footer
  = yield :footer
- else
  = render "layouts/footer_big"

(Note: HAML Syntax) Thanks.

November 26, 2009
0 thanks

How to use with HAML

Are you using HAML and try to do the block-thing (do…)? Please note that the whole block has to be in a single line. More: http://groups.google.com/group/haml/browse_thread/thread/52e62ef501c504a3

November 26, 2009
0 thanks

Streaming Does Not Work with Mongrel

If you are trying to stream output via render :text => Proc and Mongrel, be sure to note that this does NOT work. Mongrel returns a StringIO, which by nature buffers everything.

Unsure of how to actually stream output with Rails in a consistent fashion.

November 22, 2009
0 thanks

assert_response(:success) checks if the status code is in the range 200-299

success? in ActionController::TestResponseBehavior is defined as:

def success?
  (200..299).include?(response_code)
end
November 18, 2009
0 thanks

Be careful with float ranges

Pay close attention to the fact that the object passed to :in must be enumerable.

If you want to validate a ranking, the following won’t work:

validates_inclusion_of :rating, :in => (0.0..10.0)

Instead, you’ll want to use validates_numericality_of like this:

validates_numericality_of :rating, :greater_than_or_equal_to => 0.0, :less_than_or_equal_to => 10.0
November 18, 2009
0 thanks

More Docs and Explanation

You probably want to look at the class level docs

http://apidock.com/rails/ActiveRecord/NestedAttributes/ClassMethods

(cut and paste, apidocks can’t render the above for some reason)

November 16, 2009
2 thanks
November 13, 2009
1 thank

style for select

<%= select(“post”, “person_id”, Person.all.collect {|p| [ p.name, p.id ] }, {}, :style => “width:100px” %>

November 13, 2009
1 thank

Careful with scopes

Just like find, find_in_batches introduces an implicit scope into the block. So for example

Person.find_in_batches(:conditions => {:birthday => Date.today}) do |birthday_childs|
  Person.all.each do |person|
    person.send_presents_to(birthday_childs)
  end
end

does not work as expected, because the Person.all within the block will also find only persons with :conditions => {:birthday => Date.today}.

November 12, 2009
2 thanks

You can't use the :limit option either

Person.find_each(:limit => 10000)…

Will result in:

RuntimeError: You can’t specify a limit, it’s forced to be the batch_size

November 12, 2009
0 thanks

Rails documentation for nested attributes

ActiveRecord/NestedAttributes/ClassMethods

(don’t follow this link, the url interpreter isn’t rendering it correctly :(, but the correct link is at the top of this page)

November 12, 2009
8 thanks

Use hash form of updates argument

The examples are unfortunate, because passing a string as the updates argument is an invitation to SQL injection attacks. Don’t do this!

Billing.update_all("author='#{author}'")

Use the hash form of updates instead:

Billing.update_all(:author => author)

Then the SQL adapter will quote everything safely. Even if [you think] you’re sure there’s no quoting issue, it’s better to cultivate the habit of using the hash form just in case you missed something.

Same with conditions–use the hash or array form rather than a string if there are variables involved.

BTW, to do this and give options, of course you’ll need to put the braces back in:

Billing.update_all({:author => author},
                   ['title like ?', "#{prefix}%"])
November 11, 2009
2 thanks

Re: Taking care when writing regex

Oleg’s example from above contains an error and a pitfall:

validates_format_of :something => /^\w$/

The string “blahblahblah” doesn’t pass this validation. What Oleg ment is rather a continuous string of at least one alphanumeric character:

validates_format_of :something => /^\w+$/

However, that’s no good neither because it contains a well hidden trap in case you are validating content from a textarea.

Ruby (both 1.8 and 1.9) always matches ^ and $ against the beginning and ending of lines and not the entire string. Thus “First linenSecond line” will pass the above validation although it’s clearly not a continuous string.

You should use A (replacement for ^) and z (replacement for $) instead as their scope is the entire string:

validates_format_of :something => /\A\w+\z/

(A side note for those with a Perl background: Please note that the “s” modifier has a different meaning in Ruby and won’t do the trick here.)

November 11, 2009
0 thanks

Calling migrations within migrations observation

Following the advice from RISCfuture I could not call a migration from within another migration. I got the following errror message:

NameError Exception: uninitialized constant FixDrunkMistake::CreateExGirlfriendTexts.down

Only after I did a

require 'create_ex_girl_friend_texts' # the migration file

before the migration call did everything work as expected.

November 10, 2009
2 thanks

Where are the cached files?

If you configure your app to use the file_store like so:

config.cache_store = :file_store, '/tmp'

and expect you cached page pages to end up in /tmp, think again…

Rails – rather obscurely imho – will store page cached pages in the public/ folder of your app, making it easy for your webserver to find them.

The ‘page_cache_directory’ used in the ‘page_cache_path’ method above is a class var that defaults to the public/ dir.

November 5, 2009 - (>= v2.1.0)
7 thanks

Named scope better than conditions

In modern versions of Rails, in most cases a named_scope is a better alternative to using :conditions on your has_many relations. Compare:

class User
  has_many :published_posts, :conditions => {:published => true}
end
user.published_posts

with:

class Post
  named_scope :published, :conditions => {:published => true}
end
class User
  has_many :posts
end
user.posts.published

It’s better because the Post’s logic (“am I published?”) should not be coupled within User class. This makes it easier to refactor: e.g. if you wanted to refactor the boolean :published field into a :status field with more available values, you would not have to modify User class. Having to modify User when you refactor some implementation detail of Post class is clearly a code smell.

This also applies to :order, :group, :having and similar options.

November 4, 2009
2 thanks

Using hidden tags

To use an <input type=“hidden” /> tag, use the following syntax:

<% form_for(@post) do |f| %>
  <%= f.hidden_field :user_id, { :value => user.id } %>
<% end %>
November 3, 2009
0 thanks

Setting a custom Content type

The given example seems to be broken. The :mime_type option as well as the [] access on the Mime::Type class are both not working.

The following code allows the custom setting of content types as intended by the original example:

class  PostsController < ActionController::Base
  def show
     @post = Post.find(params[:id])

    respond_to do |format|
      format.html
      format.ics { render :text => post.to_ics, :content_type => Mime::Type.lookup("text/calendar")  }
      format.xml { render :xml => @people.to_xml }
    end
  end
end
November 2, 2009
0 thanks

To use the memcached gem

If you use the mem_cache_store it will use “memcache-client” to talk to the actual cache. memcache-client is a pure Ruby library that is bundled with rails. There is a Ruby/C library called “memcached” that uses native bindings to talk to memcache, and it is reportedly (http://blog.evanweaver.com/files/doc/fauna/memcached/files/README.html) up to a 100 times faster than memcache-client. To use that instead,

# in shell
$ sudo gem install memcached --no-rdoc --no-ri

# in config/production.rb
require 'memcached'
config.action_controller.cache_store =
  :mem_cache_store, Memcached::Rails.new("localhost:11211")

This feature (to pass a configured MemCache-like object to cache_store=) is available since rails 2.3.3 and will hopefully be documented in 2.3.5.

October 30, 2009
7 thanks

How FormBuilders work

What, you were expecting documentation? :)

An excellent survey of how FormBuilders work is here:

http://code.alexreisner.com/articles/form-builders-in-rails.html

October 30, 2009
0 thanks

Outputs name even if condition is false

Please note that if the condition is false, link_to_if will still output the name given as a plain text (as documented above). If you want nothing printed at all, you’ll have to stay with the old and trusty:

link_to "Login", ... if @current_user.nil?
October 30, 2009
2 thanks

Outputs name even if condition is false

Please note that if the condition is false, link_to_if will still output the name given as a plain text (as documented above). If you want nothing printed at all, you’ll have to stay with the old and trusty:

link_to "Login", ... if @current_user.nil?
October 28, 2009
7 thanks

#blank?

The opposite of this is #blank?

October 27, 2009
4 thanks

#present?

The opposite of this is #present?

October 27, 2009 - (>= v1.0.0)
1 thank

Only works within a transaction

Of course, this has to be done in a transaction, like so:

# we've loaded user earlier and did some checks which took some time
# to make sure, updates made meanwhile by other threads don't lead to
# optimistic locking errors here, we do this when finally suspending
User.transaction do
  user.lock!
  user.suspended = 1
  user.save!
end
October 23, 2009
2 thanks

Setting child_index while using nested attributes mass assignment with prototype

First of all, drogus idea really helped me. I’m not using jQuery, therefore I implemented my own version:

link_to_function

def add_object_link(name, where, render_options)
  html = render(render_options)

  link_to_function name, %{
    Element.insert('#{where}', #{html.to_json}.replace(/index_to_replace_with_js/g, new Date().getTime()));
  }
end

Using add_object_link

<%= add_object_link 'Add asset', 'assets', :partial => 'assets/asset', :object => Asset.new, :locals => { :f => f } %>
October 22, 2009 - (>= v2.1.0)
4 thanks

Update statement won't include all attributes with ActiveRecord::Dirty

With the addition of ActiveRecord::Dirty, the update statement will only feature changed columns, as opposed to the comment of railsmonk below.