Recent notes
RSS feedextend adds class methods too
Because classes are objects. So for example:
module Ispeak def says "greetings aliens!" end end module Ieat def eats "spinach" end end module Inhabitant def says "I'm strong to the finish" end end class Human extend Ispeak # add class methods from Ispeak include Inhabitant # add instance methods from Inhabitant end Human.extend Ieat # add class methods from Ieat puts Human.says # -> greetings aliens! puts Human.eats # -> spinach popeye = Human.new puts popeye.says # -> I'm strong to the finish
Attachment's name
Files attached in a standard way are shown up as “noname”. You can specify any name by using the :filename key:
attachment :content_type => "application/pdf", :filename => "Othersheet.pdf", :body => File.read("example.pdf")
:popup gotcha in IE
If your popup title contains spaces or escaped HTML characters, Internet Explorer (at least 6/7) will not pop up a new window but open the link in the existing browser window.
Add last_week to core_extensions
If you want to implement last_week as posted by Mange, save it as:
lib/core_extensions.rb
class Date 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 end
And add to:
config/environment.rb
require 'core_extensions'
session expiration
If you need to set expiration period for sessions through all controllers in your application, simply add the following option to your config/intializers/session_store.rb file:
:expire_after => 60.minutes
If you need to set different expiration time in different controllers or actions, use the following code in action or some before_filter:
request.session_options = request.session_options.dup request.session_options[:expire_after] = 5.minutes request.session_options.freeze
Duplication of the hash is needed only because it is already frozen at that point, even though modification of at least :expire_after is possible and works flawlessly.
Passing an :object to the partial
For some reason the :object option is completely undocumented. Here’s an example usage.
# Renders the partial, making @new_person available through the local variable 'person' render :partial => "person", :object => @new_person
(Credit goes to Catfish for the example, which I obtained from http://dev.rubyonrails.or/ticket/8518 )
sending an array of multiple options
To make sure that you’ll receive a array you should declare the name of the select with “[ ]” like that:
Example
<%= select_tag "users[]", options_for_select(@users.collect{|x| [x.name,x.id]}), {:multiple => :multiple, :size => 10} %>
Getting (n..end)
It would seem like it would be possible to say, get everything from element i and to the end by saying
# WRONG! a[i, -1] # "From 2 to the last element"
but since the second parameter does not say the ending index, but instead the length, this is not possible and you will get nil from the above code.
What you should do instead is using that the length can be specified longer then how long it is going to be:
b = [1, 2, 3] # Return up to a million elements # (not "return an array WITH 1 million elements") b[2, 1_000_000] #=> [3] # Size is guaranteed to never be shorter # than our returned value should be a[i, a.size]
It is a waste to do something like this:
a[i, a.size - i] a[i..(a.size-i)]
How not to find an element
assert_select ‘div’, :count => 0
Passing parameters to custom formbuilders
If you implement your own formbuilder, the options passed are available as @options inside your formbuilder. If you want those configuration options passed to all builders in the fields_for sections, use the following code in your form builder:
def fields_for_with_options(record_or_name_or_array, *args, &block) options = args.extract_options! fields_for_without_options(record_or_name_or_array, *(args << options.merge(@options)), &block) end alias_method_chain :fields_for, :options
Usage:
form_for @my_object, :builder => MyCustomFormbuilder, :some_setting => :cool
Symbol#to_proc
@tadman - or simply defining:
class Symbol def to_proc proc { |obj, *args| obj.send(self, *args) } end end
Gotcha with class_inheritable_accessor and cloneing the attribute values
The key thing to note from post is that class_inheritable_accessor copies the value from the parent class at inherit time. So, if you are setting a default value of an array and doing something like the following you might end up with unintended results:
>> A.class_inheritable_foo << 'from a' => ["from a"] >> B.class_inheritable_foo << 'from b' => ["from a", "from b"] >> C.class_inheritable_foo << 'from c' => ["from a", "from b", "from c"]
However, if you use the form:
class << self def class_instance_foo @class_instance_processors ||= [] end end
The original values aren’t copied from the parent class when you reference the class for the first time:
>> A.class_instance_foo << 'from a' => ["from a"] >> B.class_instance_foo << 'from b' => ["from b"] >> C.class_instance_foo << 'from c' => ["from c"]
Auto-submitting select tag
If you want your form to be submitted when user selects something, use:
:onchange => "this.form.submit();"
For example:
select_tag "people", "<option>David</option>", :onchange => "this.form.submit();"
Using custom object via :object
Sometimes you need use select not only with @object as by default. For example if you have helper method like :
def select_parent_for(page) select(:page, :parent_id, Page.all.collect{|p| [p.name, p.id]} ) # <--- mistake! end
In selected line you will use @page instead parameter of method page.
The options has parameter :object (and all form helpers has such parameter)
Solution:
def select_parent_for(page) select(:page, :parent_id, ..., :object => page) end
Freezing Time.now with Time.is
Sometimes when writing unit tests/specifications our code sets an attribute of an object using Time.now because running specs/test takes time.
The solution is to “freeze” Time.now with the following Time.is method:
class Time def self.metaclass class << self; self; end end # useful for unit testing # Time.is(Time.now) do # Time.now # => Tue Nov 13 19:31:46 -0500 2007 # sleep 2 # Time.now # => Tue Nov 13 19:31:46 -0500 2007 # end # # Time.is("10/05/2006") do # Time.now # => Thu Oct 05 00:00:00 -0400 2006 # sleep 2 # Time.now # => Thu Oct 05 00:00:00 -0400 2006 # end def self.is(point_in_time) new_time = case point_in_time when String then Time.parse(point_in_time) when Time then point_in_time else raise ArgumentError.new("argument should be a string or time instance") end class << self alias old_now now end metaclass.class_eval do define_method :now do new_time end end yield class << self alias now old_now undef old_now end end end
It’s a good idea to add this to your spec_helper/test_helper and “freeze” time whenever you’re testing functionality that depends on a specific time value.
Time in fixtures
When creating fixtures you should use this method to set created_at/updated_at timestamps correctly:
eg:
This won’t work as expected (created_at/updated_at will be nil) a
one: episode: active1 play_id: 1 play_time: 20 country: United Kingdom created_at: <%= Time.parse('22:00 14 Aug 2009') %> updated_at: <%= Time.parse('22:00 14 Aug 2009') %>
but this will work as expected:
one: episode: active1 play_id: 1 play_time: 20 country: United Kingdom created_at: <%= Time.parse('22:00 14 Aug 2009').to_s(:db) %> updated_at: <%= Time.parse('22:00 14 Aug 2009').to_s(:db) %>
Time in fixtures
When creating fixtures you should use this method to set created_at/updated_at timestamps correctly:
eg:
This won’t work as expected (created_at/updated_at will be nil) a
one: episode: active1 play_id: 1 play_time: 20 country: United Kingdom created_at: <%= Time.parse('22:00 14 Aug 2009') %> updated_at: <%= Time.parse('22:00 14 Aug 2009') %>
but this will work as expected:
one: episode: active1 play_id: 1 play_time: 20 country: United Kingdom created_at: <%= Time.parse('22:00 14 Aug 2009').to_s(:db) %> updated_at: <%= Time.parse('22:00 14 Aug 2009').to_s(:db) %>
Small notice about recognize urls with specific HTTP verbs
This is wrong ruby syntax:
assert_recognizes {:controller => 'items', :action => 'create'}, {:path => 'items', :method => :post}
Parentheses are obligatory in this case:
assert_recognizes({:controller => 'items', :action => 'create'}, {:path => 'items', :method => :post})
To find element ant not to find element
If you want to see administration panel:
assert_select "div.admin-panel"
But if you want to NOT see administration panel just write:
assert_no_tag 'div', :attributes => {:class => 'admin-panel'}
With multiple parameters
Example
remote_function( :url => some_remote_function_path, :with => "'key1='+$('elem_id').value +'&key2='+$('elem_id').value+ '&this_elem_value='+value" )
with_exclusive_scope example by Ramon broken in latest Rails
The example Ramon gave works within the model itself, i.e.
class Article def closed with_exclusive_scope { find(:all) } end end
However, from what I can see, this approach does not work within a controller. You may be wanting to use
Article.with_exclusive_scope { find(:all) } #=> "SELECT * FROM 'articles'
But it will error out about find(:all) not existing on ArticlesController. To get around this, you must now do
Article.with_exclusive_scope { Article.find(:all) } #=> "SELECT * FROM 'articles'
In otherwards, find(:all) isn’t being executed in the scope of the model, but in the controller in which its called.
Took me a minute or two to find out, so I thought I’d let others know.
Current Database Name: Sqlite version
Get the current database name when using Sqlite:
ActiveRecord::Base.connection.instance_variable_get(:@config)[:database].split('/').last
Common signals
Some of the more commonly used signals:
1 HUP (hang up) 2 INT (interrupt) 3 QUIT (quit) 6 ABRT (abort) 9 KILL (non-catchable, non-ignorable kill) 14 ALRM (alarm clock) 15 TERM (software termination signal)
Content type for emails with attachments
Be aware that if you want to send emails with attachments, you probably want to use the content type multipart/mixed for the overall email.
The MIME time multipart/alternative is intended for emails where each part is a different representation of the same message.
After following the 2.3.2 documentation we used multipart/alternative to attach files to our mails, however this then caused Hotmail to ignore the attachments. It turns out it thought they were all alternative versions of the HTML content (which it could already display, so the alternatives weren’t necessary)
Re: Validate an optional URL field
Actually it’s easier to use validates_format_of for this task. Please refer to the comments under the doc.
Join multiple tables
It’s easy to join multiple tables too. In this case we have:
class Article belongs_to :feed end class Feed has_many :articles belongs_to :source end class Source has_many :feeds # t.bool :visible end
You can search articles and specify a condition on the sources table.
Article.find(:all, :conditions => { :feeds => { :sources => { :visible => true }}}, :joins => [:feed => :source],
Built-in cache stores
Built-in cache stores are:
-
:file_store (ActiveSupport::Cache::FileStore)
-
:memory_store (ActiveSupport::Cache::MemoryStore)
-
:drb_store (ActiveSupport::Cache::DRbStore)
-
:mem_cache_store (ActiveSupport::Cache::MemCacheStore)
-
:compressed_mem_cache_store (ActiveSupport::Cache::CompressedMemCacheStore)
Most common use case
Most common use case is probably:
Rails.cache.fetch "some key" do compute some value end
This computes some value and caches it. Subsequent invocations will return cached value (as long as it is still cached).
Documentation
This method only returns a cache manager object of sorts, to see what you can do with it, see ActiveSupport::Cache::Store.