Good notes posted to Ruby on Rails
RSS feedMethod description from Rails 2.0
If text is longer than length, text will be truncated to the length of length (defaults to 30) and the last characters will be replaced with the truncate_string (defaults to “…”).
Examples
truncate("Once upon a time in a world far far away", 14) # => Once upon a... truncate("Once upon a time in a world far far away") # => Once upon a time in a world f... truncate("And they found that many people were sleeping better.", 25, "(clipped)") # => And they found that many (clipped) truncate("And they found that many people were sleeping better.", 15, "... (continued)") # => And they found... (continued)
:expires_in option
If you need :expires_in functionality in Rails 2.1, you can use this plugin:
http://github.com/nickpad/rails-caches-action-patch/tree/master
Turn layout off with render
Thats awkward, but the code below does not turn layout off:
render :action => "short_goal", :layout => nil
you must use false
render :action => "short_goal", :layout => false
print standard-looking messages during migration
Within a migration file you can use the say_with_time method to print out informational messages that match the style of standard migration messages. See the say method also.
say_with_time "migrate existing data" do # ... execute migration sql ... end #=> "-- migrate existing data" #=> " -> 0.0299s"
:null => false
To not allow a column to have a NULL value, pass :null => false. Seems silly, but that’s it.
Information on 'ModelName.transaction'
If you are looking for information about:
ModelName.transaction do ... end
or
transaction do ... end
Information on 'ModelName.transaction'
If you are looking for information about:
ModelName.transaction do ... end
or
transaction do ... end
Be careful with overriding dynamic attribute based finders
don’t try something like this:
class Foo < ActiveRecord::Base def self.find_by_bar(*args) foo = super(*args) raise SomeCustomException unless foo foo end end
In newer versions of rails, method_missing defines find_by_bar when you first use it. By calling super, you’re triggering method_missing and overwriting your custom definition! It will work the first time then break! Manually write the call to find!
Custom collection local variable name
Regarding the previous note from hoodow about using :variable_name to create a custom local variable name when rendering a collection with a partial, the argument should be :as instead of :variable_name, so:
render :partial => “video_listing”, :collection => @recommendations, :as => :video
This method has moved
To help anyone else looking, this method is now on the ActionView::Template class.
Testing protected controllers
When testing controllers which are protected with #authenticate_or_request_with_http_basic this is how you can supply the credentials for a successful login:
@request.env["HTTP_AUTHORIZATION"] = "Basic " + Base64::encode64("username:password")
Must be set before the request is sent through #get or whatever method.
Useful in migrations
The most common usage pattern for this method is probably in a migration, when just after creating a table you want to populate it with some default values, eg:
class CreateJobLevels < ActiveRecord::Migration def self.up create_table :job_levels do |t| t.integer :id t.string :name t.timestamps end JobLevel.reset_column_information %w{assistant executive manager director}.each do |type| JobLevel.create(:name => type) end end def self.down drop_table :job_levels end end
ActiveRecord::Base.include_root_in_json
From Rails 2.1 onwards, the variable
ActiveRecord::Base.include_root_in_json
affects how the JSON is generated. If this is true (default), then the JSON isn’t like the one above. Instead you’ll get:
konata = User.find(1) konata.to_json # => { "user": { "id": 1, "name": "Konata Izumi", "age": 16, "created_at": "2006/08/01", "awesome": true}}
(Note the model name is included as a root of the JSON object)
For Rails 2.1 generated projects, you’ll see this in the config/initializers/new_rails_defaults.rb file. You’ll need to set the value to false if you want the old behaviour.
ActiveRecord::Base.include_root_in_json = false
Always pass a block
I highly recommend always taking a block and passing it back up the chain if you use alias_method_chain, even if the original method does not. Otherwise you’re keeping anyone later in the chain from adding support for blocks.
http://tech.hickorywind.org/articles/2008/08/29/always-pass-a-block-when-using-alias_method_chain
Brazilian Real (R$ 1.200,95)
helper:
def number_to_currency_br(number) number_to_currency(number, :unit => "R$ ", :separator => ",", :delimiter => ".") end
Get year to show in descending order (Today to 1920 for example)
The way people think of time start and end would be 1920 to today. This made me think “but I want it show the current year first then down.” Well it’s as simple as swapping the start_year and end_year.
date_select :date, :start_year => Date.current.year, :end_year => 1920 # => 2008, 2007, 2006, 2005 ... 1920
Moved to ActiveRecord::Calculations::ClassMethods
It appears that this method has simply been moved to the module ActiveRecord::Calculations::ClassMethods. You can still use the example listed in the docs here, it will simply call the method ActiveRecord::Calculations::ClassMethods#count.
When using RESTful routes
I had issues using expire_page with RESTful controllers when expiring anything other than the index action because I was basing my expire_page calls off this example.
The solution is to use my_resource_path for example when User with id 5 is updated, you would have to do:
expire_page user_path(user) # or expire_page formatted_user_path(user, :xml)
This may apply to early versions but I have only tested on v2.1.0
Only attr_accessible attributes will be updated
If your model specified attr_accessible attributes, only those attributes will be updated.
Use attr_accessible to prevent mass assignment (by users) of attributes that should not be editable by a user. Mass assignment is used in create and update methods of your standard controller.
For a normal user account, for example, you only want login and password to be editable by a user. It should not be possible to change the status attribute through mass assignment.
class User < ActiveRecord::Base attr_accessible :login, :password end
So, doing the following will merrily return true, but will not update the status attribute.
@user.update_attributes(:status => 'active')
If you want to update the status attribute, you should assign it separately.
@user.status = 'active' save
Prototype hinted_text_field application_helper
Place this in your helper. It will show a message inside the text box and remove it when someone clicks on it. If they don’t enter a value when they leave the field it’ll replace the message. (Requires javascript :defaults).
def hinted_text_field_tag(name, value = nil, hint = "Click and enter text", options={}) value = value.nil? ? hint : value text_field_tag name, value, {:onclick => "if($(this).value == '#{hint}'){$(this).value = ''}", :onblur => "if($(this).value == ''){$(this).value = '#{hint}'}" }.update(options.stringify_keys) end # inside form_for example hinted_text_field_tag :search, params[:search], "Enter name, brand or mfg.", :size => 30 # => <input id="search" name="search" onblur="if($(this).value == ''){$(this).value = 'Enter name, brand or mfg.'}" onclick="if($(this).value == 'Enter name, brand or mfg.'){$(this).value = ''}" size="30" type="text" value="Enter name, brand or mfg." />
Customizing prompt
The :prompt option not only accepts a boolean value. It can also be given a string to define another than the standard prompt ‘Please select’. Referring to the example it could read:
collection_select(:post, :author_id, Author.find(:all), :id, :name_with_initial, {:prompt => 'Please select the author of this post'})
Rake tasks for gem dependencies
You can manage installation and other tasks for these dependencies with rake tasks, for example:
rake gems:install # Installs all required gems for this application rake gems:unpack # Unpacks the specified gem into vendor/gems
To get all rake tasks about gems:
rake -T gems
Disable default date
If you want a date selector that initially doesn’t have a date selected you can pass it the option :include_blank.
date_select("project", "due_date", :include_blank => true)
%w(true false) != [true, false]
Don´t confuse the right:
validates_inclusion_of :published, :in => [true, false]
with the wrong:
validates_inclusion_of :published, :in => %w(true false)
cause:
%w(true false) == ["true", "false"]
Include two level has many model example
class Issue < ActiveRecord::Base
has_many :journals end class Journal < ActiveRecord::Base belongs_to :issue has_many :details, :class_name => "JournalDetail", :dependent => :delete_all end class JournalDetail < ActiveRecord::Base belongs_to :journal end
<hr/>
issue = Issue.find(:first, :include => {:journals => :details} log record follow: SELECT * FROM `issues` LIMIT 1 SELECT `journals`.* FROM `journals` WHERE (`journals`.`journalized_id` IN (1) and `journals`.`journalized_type` = 'Issue' AND (dustbin <> 1)) SELECT `journal_details`.* FROM `journal_details` WHERE (`journal_details`.journal_id IN (1,2,876177898,935815637)) when execute follow code, then not build sql sentent: issue.journals issue.journals[0].details
Doesn't add an index
Typically you will want to have an index on foreign keys but this method doesn’t assume that. Outside of the create_table block you should follow this with add_index :
add_index :table_name, :goat_id # and, if polymorphic: add_index :table_name, :goat_type


