Flowdock

Recent notes

RSS feed
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 9, 2009
0 thanks

overwrite

Replacing old value with new one

>> Module.const_set('MY_CONSTANT', 'value')
=> "value"
>> Module::MY_CONSTANT
=> "value"
>> Module.const_set('MY_CONSTANT', 'new value')
(irb):3: warning: already initialized constant MY_CONSTANT
=> "new value"
>> Module::MY_CONSTANT
=> "new value"

or

>> Kernel.const_set('MY_CONSTANT', 'value')
=> "value"
>> MY_CONSTANT
=> "value"
>> Kernel.const_set('MY_CONSTANT', 'new value')
(irb):3: warning: already initialized constant MY_CONSTANT
=> "new value"
>> MY_CONSTANT
=> "new value"
November 5, 2009
9 thanks

define_method with parameters

Just to be clear, you can do this:

define_method(:my_method) do |foo, bar| # or even |*args|
  # do something
end

This means same as:

def my_method(foo, bar)
  # do something
end

If you want to define method with parameters that have default values, you need to get a bit more creative and do something like this:

define_method(:my_method) do |foo, bar|
  bar ||= {}
  # do something
end
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 31, 2009
2 thanks

Don't forget to require 'tmpdir'

If you simply say Dir.tmpdir you might get a nice surprise:

irb> Dir.tmpdir
NoMethodError: undefined method `tmpdir' for Dir:Class

from (irb):1

Strangely, this method seems to be stored in a file that Ruby doesn’t require by default. Just require 'tmpdir' and all should be well.

irb> require 'tmpdir'
=> true
irb> Dir.tmpdir
=> "/var/folders/An/AnwlXPZFH2aRLCERERQDKE+++TI/-Tmp-"
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
3 thanks

Map-like Manipulation of Hash Values

Let’s say you want to multiply all values of the following hash by 2:

hash = { :a => 1, :b => 2, :c => 3 }

You can’t use map to do so:

hash.map {|k, v| v*2 }   # => [6, 2, 4]

However, with merge you can:

hash.merge(hash) {|k,v| v*2 }   => {:c=>6, :a=>2, :b=>4}

(The above is Ruby 1.8, in Ruby 1.9 the order is preserved.)

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.

October 20, 2009
3 thanks

See Dir#glob

See glob for more usage information and comments.

October 20, 2009
2 thanks

Getting relative path from absolute globbing

Say you want to scan for files in directory base_dir and you want to use the relative path from this base dir, you could do it like this:

base_dir = '/path/to/dir'
files = Dir[File.join(base_dir, '**', '*.yml')]

# files now contain absolute paths:
files.first # => "/path/to/dir/foo/bar.yml"

# let's make them relative
base_pathname = Pathname.new(base_dir)
files = files.collect do |file|
  Pathname.new(file).relative_path_from(base_pathname)
end

files.first # => "foo/bar.yml"

Of course, a more common use-case could be the following:

def scan_for_documents!
  base_path = Pathname.new(self.base_path)
  self.contained_files = []
  Dir[File.join(self.base_path, '**', '*.pdf')].each do |full_path|
    path = Pathname.new(full_path).relative_path_from(base_path)
    self.contained_files << path
  end
end
October 19, 2009
1 thank

Get all inner texts

Extend REXML::Element so that it can get the first text and following inner texts (child texts included) of the current element as array and as string:

class REXML::Element

 def inner_texts
  REXML::XPath.match(self,'.//text()')
 end

 def inner_text
  REXML::XPath.match(self,'.//text()').join 
 end

end
October 18, 2009
1 thank

Receiving data over UDP

It’s perfectly normal to receive ‘X’ strings with Ruby’s UDP sockets before the actual content.

Consider the following example:

require 'socket'

PORT = 5500

socket = UDPSocket.new
socket.bind('', PORT)

for i in 1..10
  IO.select([socket])
  p socket.recvfrom_nonblock(4096)
end

Now, sending data with netcat:

echo "Hello APIdock" | nc -vv -u 127.0.0.1 5500

The application would output:

["X", ["AF_INET", 61755, "localhost", "127.0.0.1"]]
["X", ["AF_INET", 61755, "localhost", "127.0.0.1"]]
["X", ["AF_INET", 61755, "localhost", "127.0.0.1"]]
["X", ["AF_INET", 61755, "localhost", "127.0.0.1"]]
["Hello APIdock\n", ["AF_INET", 61755, "localhost", "127.0.0.1"]]
October 17, 2009
1 thank

Re: Passing parameters to before_filter

I am not sure I get your “method 1” alec-c4; won’t that define the method each time the before_filter is called? Why not just define the method in the controller?

You can pass parameters or call protected methods with instance_eval:

before_filter :only => :show do |controller|
  controller.instance_eval do
    redirect_to edit_object_path(params[:id])
  end
end
October 16, 2009 - (>= v2.1.0)
1 thank

No numbers or symbols

“Kyle”, “Дети”, “Niños”, “Quan-lu”, “た ち”

validates_format_of :first_name, :with => /^([^\d\W]|[-])*$/
October 15, 2009
4 thanks

Have check_box checked by default

In addition to comment below, you can make a column with default value so in your forms it will be enabled by default and behave correctly with validation errors unlike :checked => true

in your migration

add_column :accounts, :ssl_enabled, :boolean, :default => 1
October 15, 2009
2 thanks
October 14, 2009
2 thanks

build_association deletes existing dependent record

Surprisingly (at least I was surprised), when an associated record exists, the build_association method immediately NULLs the foreign key in the database.

So if you write a singleton “new” action for the association in the obvious way (calling build_association), then just visiting the page will disconnect an existing associated record. This violates the principle that a GET request shouldn’t affect the database.

To avoid this, you can check for an existing association first, and redirect to the show action.

October 12, 2009
0 thanks

Use it to solve FixtureClassNotFound errors.

If you are using a non standard table name by means of set_table_name in your model:

class MyClassName < ActiveRecord::Base
  set_table_name "mytablename"
end

then you will get FixtureClassNotFound errors when you try to use fixtures in you unit tests. To solve this use set_fixture_class inside your test:

require 'test_helper'
class MyClassNameTest < ActiveSupport::TestCase
  set_fixture_class :mytablename => MyClassName  
end

and rename your fixture file to mytablename.yml

October 10, 2009
2 thanks

Example

[5,6,7].each_with_index do |x,i|

puts "#{i} -> #{x}"

end

Outputs: 0 -> 5 1 -> 6 2 -> 7