Notes posted by szeryf
RSS feedExamples in a readable format :)
Here are the above examples in a somewhat more readable format:
# Assert a basic route: a controller with the default action (index) assert_routing ‘/home’, :controller => ‘home’, :action => ‘index’ # Test a route generated with a specific controller, action, and parameter (id) assert_routing ‘/entries/show/23’, :controller => ‘entries’, :action => ‘show’, :id => 23 # Assert a basic route (controller + default action), with an error message if it fails assert_routing ‘/store’, { :controller => ‘store’, :action => ‘index’ }, {}, {}, ‘Route for store index not generated properly’ # Tests a route, providing a defaults hash assert_routing ‘controller/action/9’, {:id => “9”, :item => “square”}, {:controller => “controller”, :action => “action”}, {}, {:item => “square”} # Tests a route with a HTTP method assert_routing({ :method => ‘put’, :path => ‘/product/321’ }, { :controller => “product”, :action => “update”, :id => “321” })
Undocumented :location option
You can use undocumented :location option to override where respond_to sends if resource is valid, e.g. to redirect to products index page instead of a specific product’s page, use:
respond_with(@product, :location => products_url)
Dynamic exists? methods
There are no dynamic exists? methods analogous to dynamic finders, which means that while you can do this:
Person.find_by_name('David')
you can’t do this:
Person.exists_by_name('David') # DOES NOT WORK
nor this:
Person.exists_by_name?('David') # DOES NOT WORK
However, you can simulate this with dynamic scope:
Person.scoped_by_name('David').exists?
You’ll have to admit that this is so much better than the plain old method:
Person.exists?(:name => "David")
Does not work with polymorphic relations
If you have polymorphic relations, e.g.:
class Bookmark < ActiveRecord::Base belongs_to :thing, :polymorphic => true belongs_to :owner, :polymorphic => true end
and you want to ensure that a thing can bookmarked by an owner at most once, you can’t do this:
validates_uniqueness_of :thing, :scope => :owner
Instead, you must use the real column names, e.g.:
validates_uniqueness_of :thing_id, :scope => [:thing_type, :owner_id, :owner_type]
Wrong example
In the authentication filter example above, the time condition should be reversed: we only want to find the user if time is still in the future (because it’s the valid-until time).
So the example should look like this:
id, time = @verifier.verify(cookies[:remember_me]) if time > Time.now self.current_user = User.find(id) end
Use message param
The message param is invaluable in case test fails – if you use it to display relevant info, you will find out what went wrong much faster.
Reworking the silly example above:
assert some_list.include?(5)
will only tell you that
<false> is not true.
which isn’t terribly helpful, is it? But if you use message like that:
assert some_list.include?(5), "some_list = #{some_list.inspect}"
the output will be:
some_list = [1, 2]. <false> is not true.
which in most cases should give you strong hints as to why the test failed.
Available statuses
All the available statuses (extracted from SYMBOL_TO_STATUS_CODE hash) in a slightly more readable form:
:continue => 100 :switching_protocols => 101 :processing => 102 :ok => 200 :created => 201 :accepted => 202 :non_authoritative_information => 203 :no_content => 204 :reset_content => 205 :partial_content => 206 :multi_status => 207 :im_used => 226 :multiple_choices => 300 :moved_permanently => 301 :found => 302 :see_other => 303 :not_modified => 304 :use_proxy => 305 :temporary_redirect => 307 :bad_request => 400 :unauthorized => 401 :payment_required => 402 :forbidden => 403 :not_found => 404 :method_not_allowed => 405 :not_acceptable => 406 :proxy_authentication_required => 407 :request_timeout => 408 :conflict => 409 :gone => 410 :length_required => 411 :precondition_failed => 412 :request_entity_too_large => 413 :request_uri_too_long => 414 :unsupported_media_type => 415 :requested_range_not_satisfiable => 416 :expectation_failed => 417 :unprocessable_entity => 422 :locked => 423 :failed_dependency => 424 :upgrade_required => 426 :internal_server_error => 500 :not_implemented => 501 :bad_gateway => 502 :service_unavailable => 503 :gateway_timeout => 504 :http_version_not_supported => 505 :insufficient_storage => 507 :not_extended => 510
Good way to see what went wrong
Use the message parameter like that:
assert_response :success, @response.body
If this fails (the response isn’t a success), it will display the response body along with the failure message, thus allowing you to quickly find out what went wrong. If the response is e.g. 500, there will probably be some exception stacktrace displayed in the body. And so on.
Possible gotcha
This method returns a Pathname object which handles paths starting with a / as absolute (starting from the root of the filesystem). Compare:
>> Rails.root => #<Pathname:/some/path/to/project> >> Rails.root + "file" => #<Pathname:/some/path/to/project/file> >> Rails.root + "/file" => #<Pathname:/file> >> Rails.root.join "file" => #<Pathname:/some/path/to/project/file> >> Rails.root.join "/file" => #<Pathname:/file>
Easy workaround for missing :through option
Note that belongs_to does not support :through option like has_many (although IMHO it would make sense in some cases), but you can easily simulate it with delegate.
For example:
class Person < ActiveRecord::Base belongs_to :team ... end class Task < ActiveRecord::Base belongs_to :person delegate :team, :to => :person end
There is of course more ways to do it, but this seems to be the easiest to me.
Undeprecated version
The undeprecated version of this function is here: ActionView::Helpers::PrototypeHelper#link_to_remote
Replacing with "\" and match — a simple solution
A somewhat different approach to the same problem:
v.gsub(/(?=\W)/, '\\') #=> Foo\ Bar\!
But from what you are trying to achieve I suspect you might be interested in Regexp.escape method :)
Attribute names are Strings, not Symbols
Another possible gotcha – the returned hash keys are of type String, not Symbol:
user.attributes["login"] # => "joe" user.attributes[:login] # => nil
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.
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?
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?
Current version
See ActiveSupport::Memoizable for un-deprecated version.
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();"
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)
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.
Instance method
Please note that this is an instance method, not a class method (which seemed more logical for me and took me a while to see what’s wrong). So, you call it like this:
User.new.from_json '{"id": 1, "name": "DHH"}' # RIGHT!
not like this:
User.from_json '{"id": 1, "name": "DHH"}' # WRONG!
Usage example
Usage example:
cube = lambda {|x| x * x * x } cube.call(3) # => 27 cube.call(6) # => 216
Not for floats
You should use assert_in_delta when comparing floating-point numbers.
Any base logarithm
Using basic arithmetic you can get logarithm with any base:
def log_with_base base, num Math.log(num) / Math.log(base) end
Examples:
>> log_with_base 2, 10 => 3.32192809488736 >> log_with_base 2, 2 => 1.0 >> log_with_base 2, 4 => 2.0 >> log_with_base 2, 16 => 4.0 >> log_with_base 4, 16 => 2.0
Any base logarithm
Using basic arithmetic you can get logarithm with any base:
def log_with_base base, num Math.log(num) / Math.log(base) end
Examples:
>> log_with_base 2, 10 => 3.32192809488736 >> log_with_base 2, 2 => 1.0 >> log_with_base 2, 4 => 2.0 >> log_with_base 2, 16 => 4.0 >> log_with_base 4, 16 => 2.0
Antonym of empty?
The antonym of empty? is Enumerable#any? method:
[].empty? #=> true [].any? #=> false [1].empty? #=> false [1].any? #=> true
Be cautious however, if your array might contain nil’s or false’s:
[false, nil].any? #=> false
Expensive method!
This method builds the a new hash every time it’s called, so be cautious not to use it in loops etc.
You can call several times
You can call it several times, like:
class Comment < ActiveRecord::Base validate :must_be_friends validate :must_be_awesome ...
or with several arguments:
class Comment < ActiveRecord::Base validate :must_be_friends, :must_be_awesome ...