Recent notes
RSS feedUsing strings as association names
Beware, that using strings as association names, when giving Hash to :include will render errors:
The error occurred while evaluating nil.name
So, :include => [‘assoc1’, ‘assoc2’ ] will work, and :include => [ {‘assoc1’ => ‘assoc3’}, ‘assoc2’] won’t. Use symbols:
Proper form
:include => [ {:assoc1 => :assoc3}, ‘assoc2’]
Format not coming out properly?
Date, Time and DateTime may have different formats defined.
If you do:
@user.created_at.to_formatted_s(:long_ordinal)
You will get (or something):
April 16th, 2009 22:03
But if you do:
@user.created_at.to_date.to_formatted_s(:long_ordinal)
You will get:
April 16th, 2009
So, be sure you know which one you are working with.
To throw an exception, use Kernel#raise
Other languages use the term throw for raising exceptions, but Ruby has a specific raise call for that.
Do not forget to add indexes
Don’t forget to add indexes to HATM table:
add_index :developers_projects, [:developer_id, :project_id]
Merges with inherited values from super class
http://www.spacevatican.org/2008/8/19/fun-with-class-variables
“When you set a class_inheritable_array or a class_inheritable_hash you are actually concatenating (or merging) with the value inherited from the super class.”
Code example
class Base class_inheritable_hash :attrs self.attrs = {:name => 'Fred'} end class Derived < Base self.attrs = {:export => 'Pain'} end Derived.attrs #=> {:name => 'Fred', :export => 'Pain'}
strip_tags method not functioning in controllers, models, or libs
It comes up with an error about white_list_sanitizer undefined in the class you’re using it in. To get around this, use:
ActionController::Base.helpers.strip_tags('string')
To shorten this, add something like this in an initializer:
class String def strip_tags ActionController::Base.helpers.strip_tags(self) end end
then call it with:
'string'.strip_tags
strip_links method not functioning in controllers, models, or libs
It comes up with an error about white_list_sanitizer undefined in the class you’re using it in. To get around this, use:
ActionController::Base.helpers.strip_links('string')
To shorten this, add something like this in an initializer:
class String def strip_links ActionController::Base.helpers.strip_links(self) end end
then call it with:
'string'.strip_links
sanitize method not functioning in controllers, models, or libs
It comes up with an error about white_list_sanitizer undefined in the class you’re using it in. To get around this, use:
ActionController::Base.helpers.sanitize('string')
To shorten this, add something like this in an initializer:
class String def sanitize ActionController::Base.helpers.sanitize(self) end end
then call it with:
'string'.sanitize
Corrected link to ActiveRecord's "new_record?" method
rafaelrosafu, the correct tink to ActiveRecord’s “new_record?” method is:
"http://apidock.com/rails/ActiveRecord/Base/new_record%3F"
Cycle with first and last
I needed a cycle that was also aware of the first and last items in the collection. This is adapted from a snippet I found while Googling:
def cycle_with_first_last(object, collection, options = { }) addition = "" addition += " #{options[:first]}" if object == collection.first addition += " #{options[:last]}"if object == collection.last cycle(options[:odd], options[:even]) + addition end
Just put that in your helpers…
Extracting the First Element
To extract the first element from an Array, use shift:
array = [ 1, 2, 3 ] # => [ 1, 2, 3 ] array.first # => 1 array # => [ 1, 2, 3 ] array.shift # => 1 array # => [ 2, 3 ]
Extracting the Last Element
To remove the last element from the Array, use pop:
array = [ 1, 2, 3 ] # => [ 1, 2, 3 ] array.last # => 3 array # => [ 1, 2, 3 ] array.pop # => 3 array # => [ 1, 2 ]
Parameters for Hash#inject
When running inject on a Hash, the hash is first converted to an array before being passed through.
The typical Enumerable#inject approach would be to simply capture the value:
array.inject(...) do |c, v| end
In the case of a Hash, v is actually a key/value pair Array. That is the key is v.first and the value is v.last, however using the pair this way is awkward and can lead to confusion.
Better to simply expand the parameters in the block definition:
hash.inject(...) do |c, (k, v)| end
Where c is the traditional carry variable and k/v represent key and value respectively.
Example
This function can be used to pass the ID of selected item, for example:
# with select or collection_select helpers: { :onchange => remote_function(:url => { :action => 'do_smth' }, :with => "'id=' + $('the_id').value") } # and grab ID in controller action as usually: YourModel.find(params[:id])
Known unknowns
In case it isn’t obvious - this is what you use when you’re fleshing out all the tests that you haven’t written yet. eg if you have a set of twenty tests for a complex piece of functionality, and just want to write out the “should” declarations (or equivalent), so you don’t forget all the corner cases… then fill out the tests themselves. Putting an assert_fail makes sure you notice if you forget to come back and fill in the body of a test.
Testing HTTP Digest authentication
Testing HTTP Digest authentication is a bit tricky. I wrote a post describing how to accomplish it.
http://lightyearsoftware.com/blog/2009/04/testing-http-digest-authentication-in-rails/
Note also that Digest auth is broken for REST actions using PUT or DELETE. There is an open Lighthouse ticket for this, #2490:
rails.lighthouseapp.com/projects/8994/tickets/2490-http-digest-auth-uses-wrong-request-method-for-put-delete
Using global $! to address exception
@noxyu3m: Your code is actually syntactically wrong. The global is called $!
Your code should have been:
def create @model = Model.new(params[:model) @model.save! rescue logger.error($!.to_s) end
Although I would prefer
def create @model = Model.new(params[:model) @model.save! rescue ActiveRecord::RecordInvalid logger.error($!.to_s) end
to only catch expected exceptions, just like the documentation proposed.
Re: Force initial value
An alternative to @eric_programmer’s would be to extract it entirely from the controller logic…
class Person def sender self[:sender] || 'contact@host.com' end end
There are a ton of ways to do it, but making this a business logic decision will let you get the same logic from any possible implementation angle. Scripts, web service, etc.
To find a tag with an id or class
assert_select ‘td.highlight’, { :count => 2 }
finds 2 td tags with the highlight class.
assert_select ‘div#special’
finds div with id=special
Takes attribute as a symbol
Attribute must be passed as a symbol:
User.toggle(:funny)
not
User.toggle(funny)
Deprecation warning for old-style options
You will get a warning if you don’t define your separators as a hash:
DEPRECATION WARNING: number_with_delimiter takes an option hash instead of separate delimiter and precision arguments
So while you can still use that style, it’s not without a scolding.
Outside of app code
How do I call this from script/console?
Define handlers in order of most generic to most specific
The later the definition of the rescue handler, the higher the priority:
rescue_from Exception, :with => :error_generic rescue_from Exception::ComputerOnFire, :with => :panic
Declaring the Exception catch-all handler last would have the side-effect of precluding any other handlers from running.
This is what is meant by being “searched…from bottom to top”.
Method has moved to ActionController::Rescue::ClassMethods module
This method has simply moved, still works the same way in 2.3+
New location: ActiveSupport::Rescuable::ClassMethods#rescue_from
Like select_values for multiple values
The names are somewhat confused:
Model.connection.select_values("SELECT id,name FROM users") => ["1","2","3"] Model.connection.select_rows("SELECT id,name FROM users") => [["1","amy"],["2","bob"],["3","cam"]]
select_values returns Strings for MySQL
This method will return all values as strings from MySQL. It is easy to convert if required, for example, to integers:
select_values("SELECT id FROM companies LIMIT 3") => ['1','2','3'] select_values("SELECT id FROM companies LIMIT 3").collect(&:to_i) => [1,2,3]
use create table :force => true
if you want to drop a table before creating one in a migration, use the :force => true option of the create_table method