Recent notes
RSS feedAdd if before Ajax.request
Use link_to_remote’s before
link_to_remote(“watcher”, {:url => “/watchers/add”, :before => “if($F(‘user_id’)==”){return false;}” })
<a onclick=“if($F(‘user_id’)==”){return false;}; new Ajax.Request(‘/watchers/add’, {asynchronous:true, evalScripts:true, parameters:”}); return false;”>添加订阅人
Add empty option and text is -select-
select :object, :method, options, :prompt => ‘-select-’
Getting textfield values into "link_to_remote" via Javascript Prototype
Use Prototype to get the value of a text field via Javascript, to pass to the ‘link_to_remote’ helper using code similar to below:
link_to_remote 'Link Name', {:update => "foo", :url => {:controller => "bar", :action => "baz"}, :with => "'model[textfield]=' + $F('textfield_id')"}
Connections to multiple databases
establish_connection can be used to connect to multiple databases. The immediate downside is that your rake migrations may not work properly without hacking.
In each model that resides in a different database we call:
establish_connection :different_database
You can check they are working by hitting script/console with:
>> App.connection.instance_eval {@config[:database]} => "app_development" >> AnotherDatabase.connection.instance_eval {@config[:database]} => "another_database"
Now doing a call to AnotherDatabase.find() will connect to the AnotherDatabase database and start returning results.
error in block code example
I guess there’s an error in this part of the code:
link_to_function("Show me more", nil, :id => "more_link") do |page| page[:details].visual_effect :toggle_blind page[:more_link].replace_html "Show me less" end
It doesn’t work. It should be:
link_to_function("Show me more", nil, :id => "more_link") do |page| page[:details].toggle "Blind" page[:more_link].replace_html "Show me less" end
Using Rails 2.1.0
Rails 2.1 caching internals
Rails 2.1 caching features are pretty much undocumented. Rob Anderton has documented some internal stuff here:
http://www.thewebfellas.com/blog/2008/6/9/rails-2-1-now-with-better-integrated-caching
benchmark and silence methods
benchmark (title, log_level = Logger::DEBUG, use_silence = true) {|| …}
Log and benchmark the workings of a single block and silence whatever logging that may have happened inside it (unless use_silence is set to false).
The benchmark is only recorded if the current level of the logger matches the log_level, which makes it easy to include benchmarking statements in production software that will remain inexpensive because the benchmark will only be conducted if the log level is low enough.
silence () {|| …}
Silences the logger for the duration of the block. To silence the logger in your controller, simply use:
NameOfController.logger.silence do
# your code here...
end
:case_sensitive is on by default?
In contrast to what the documentation said, :case_sensitive seems to be on by default. This is the case with MySQL at least, I’m not sure about other databases.
Better explanation for ActionController sweepers
The first sentence in this description is confusing. http://codelevy.com/articles/2008/03/04/rails-caching-sweepers-controllers-and-models explains it more clearly.
Use the :as option for SEO friendly URLs
The :as option to map.resources can be used to generate SEO friendly URLs like so:
Code Example
map.resources :operating_systems, :as => 'operating-systems' # operating_systems_path => /operating-systems
Turns hash keys into symbols
This method is part of ActiveSupport, which is a collection of classes and standard library extensions that are useful for Rails.
symbolize_keys! returns a new hash with all keys converted to symbols.
This can be helpful when you have a non-ActiveRecord model and you want your initialize method to take a hash of parameters. If you symbolize the hash, you can extract your parameters regardless of whether initialize received a hash of strings or hash of symbols.
Passing find() arguments
I you need to pass additional arguments to a scope (e.g. limit), do this:
Shirt.colored('red').all(:limit => 10)
Rails defined Mime Types
Here are all the default Rails Mime Types:
"*/*" => :all "text/plain" => :text "text/html" => :html "application/xhtml+xml" => :html "text/javascript" => :js "application/javascript" => :js "application/x-javascript" => :js "text/calendar" => :ics "text/csv" => :csv "application/xml" => :xml "text/xml" => :xml "application/x-xml" => :xml "text/yaml" => :yaml "application/x-yaml" => :yaml "application/rss+xml" => :rss "application/atom+xml" => :atom "application/json" => :json "text/x-json" => :json
Default Mime Types
This module sets up all the default mime-types. Here they are:
"*/*" => :all "text/plain" => :text "text/html" => :html "application/xhtml+xml" => :html "text/javascript" => :js "application/javascript" => :js "application/x-javascript" => :js "text/calendar" => :ics "text/csv" => :csv "application/xml" => :xml "text/xml" => :xml "application/x-xml" => :xml "text/yaml" => :yaml "application/x-yaml" => :yaml "application/rss+xml" => :rss "application/atom+xml" => :atom "application/json" => :json "text/x-json" => :json
x-sendfile
Rails 2.1 supports the x_sendfile apache module:
send_file '/path/to.png', :x_sendfile => true, :type => 'image/png'
Handy for adding theme support
I’m using this to add basic theme support to my app:
append_view_path(File.join(RAILS_ROOT, "app/themes/#{@current_theme}")) append_view_path(File.join(RAILS_ROOT, 'app/themes/_base'))
Common templates go in app/themes/_base and then you can override these with specific theme versions in each theme directory.
How to test different responses in controller tests/specs
When you want to write a controller test or spec (rspec) to test out a different response type other than html, just set the HTTP_ACCEPTS header like so before the request:
@request.env['HTTP_ACCEPT'] = "application/rss" post :create, :blog => {}
Custom MIME Type
After you register a custom Mime::Type like stated above, you can do:
respond_to do |format| # .jpg corresponds to the second argument passed to #register # Mime::Type.register "image/jpg", :jpg format.jpg { ...do something here... } end
:expires_in not in Rails 2.1
AFAIK this is from a patch to Rails 2.1, which hasn’t been accepted yet.
Also, I think it needs to be supported by the cache_store you’re using.
collection.exists?(conditions)
The created association method also supports the ‘exists?’ method, similar to ActiveRecord::Base#exists?
has_and_belongs_to_many :categories ... categories.exist?(1) # Check whether there's a relation with a Category # object whose id is 1. categories.exist?(:id => 1) # ditto categories.exist?(['id', 1]) # ditto categories.exist?(:name => 'Anime')
update_on and update_at only set on attribute change
If you call save, and no attributes are “dirty” (changed), then an update query will not happen against the database, and thus updated_at and updated_on will not be set.
You’ll need to modify at least one field to get updated_at and updated_on to set themselves.
Bang methods also need will_change!
As it says here at the bottom if you do in-place modifications using << you’ll need to call the will_change method!
This also goes for bang methods. So:
person = Person.first person.name.downcase! person.save
will not save anything! Save will never be called. To get the name saved you need to do
person = Person.first person.name_will_change! person.name.downcase! person.save
This will save the name.
Set cache time-to-live
You can specify time-to-live for the cached item in seconds with :expires_in option.
class ListsController < ApplicationController caches_action :index, :expires_in => 1.hour end
Nil V.S. Empty String HTML Options
There is a difference between an empty string and nil value for options hash.
Code Sample
content_tag( :div, 'Hello World!', :class=>'') # => "<div class="">Hello World!</div>" content_tag( :div, 'Hello World!', :class=>nil) # => "<div>Hello World!</div>"
Using memcached as a session store
Because of Ruby’s CGI library limitations, store cannot have any configuration options. Basically this means that you cannot easily run memcached on a different port (or with any non-default settings for that matter).
You can bypass this limitation with this ugly hack (environment.rb):
cache_params = *([memcache_servers, memcache_options].flatten) CACHE = MemCache.new(*cache_params) ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS.merge!({ 'cache' => CACHE })
In your initializer block, just configure session_store normally:
config.session_store = :mem_cache_store
I think this should be fixed to work like cache_store= does.