Recent notes
RSS feed![Default_avatar_30](https://www.gravatar.com/avatar/6dd10772cfa5333c5db924091464ed95?default=http://apidock.com/images/default_avatar_30.png&size=30)
Routes = RouteSet.new
In config/routes.rb you can see this:
ActionController::Routing::Routes.draw do |map| #routes end
If you want to look at the code in ActionController::Routing you won’t find the definition of Routes. That’s because it’s actually an instance of the class RouteSet, defined in action_controller/routing.rb
Routes = RouteSet.new
![Default_avatar_30](https://www.gravatar.com/avatar/6dd10772cfa5333c5db924091464ed95?default=http://apidock.com/images/default_avatar_30.png&size=30)
How to test different responses of respond_to
You can shorten this:
@request.env['HTTP_ACCEPT'] = "application/rss"
To this:
@request.accept = "application/rss"
Also, if you send more than one Mime type, it will render the first one:
@request.accept = "text/javascript, text/html" #=> renders JS @request.accept = "text/html, text/javascript" #=> renders HTML
![Default_avatar_30](https://www.gravatar.com/avatar/bab1a2e4449e412ede5696e9b2539c55?default=http://apidock.com/images/default_avatar_30.png&size=30)
Adding "alt" text to the image tag
<%= image_submit_tag (“create.gif”, :alt => “Create new entity”) %>
This way when the images are disabled or don’t work you get the nice custom text instead of the standard one. Pretty useful.
![Default_avatar_30](https://www.gravatar.com/avatar/5866464ebc16b5c4729fff4fe7d8fbe7?default=http://apidock.com/images/default_avatar_30.png&size=30)
Alternate for Rails 2.0
Obviously these methods are protected so usage in an app is discouraged. But if you need to use it anyway for some reason Rails 2.0 also has sanitize_sql_for_conditions which operates exactly like sanitize_sql used to (i.e. it determines if it needs to be processed as an array or hash). So if you are going to blow by the protected status might as well use the easier version. :)
![Default_avatar_30](https://www.gravatar.com/avatar/1b2792536d87aa21bc739c14980fa103?default=http://apidock.com/images/default_avatar_30.png&size=30)
Correct way to quote for the shell
A followup for my previous comment;
I actually found a good way to handle quoting for the shell in Ruby 1.9 in case you really need to (for example to pipe the output from the examples I gave below).
require 'shellwords' escape = lambda { |str| Shellwords.shellescape(str) } file = %(Peter "Smiley" McGraw.txt) puts "grep foobar #{escape[file]} > foobars" # => grep foobar "Peter \"Smiley\" McGraw.txt" > foobars
Do note that I have not tested this since I do not have Ruby 1.9 installed, but from what I have read, this should work properly there.
I still do not know a good way to do this in Ruby 1.8.
![Default_avatar_30](https://www.gravatar.com/avatar/56b4f519148bc81868d714aef2cd889a?default=http://apidock.com/images/default_avatar_30.png&size=30)
Using fields_for with has_many associations
If you want to edit each element of an array of objects (such as with a has_many type association), you will need to include “[]” in your field parameter name, like so:
<% fields_for "object[]" do |subfield| -%> [...] <% end -%>
Because you named the field parameter “object[]”, fields_for will assume you have an instance variable @object to use for the fields’ values. To fake this, you can do something like:
<% objects.each do |@object| -%> <% fields_for "object[]" do |subfield| -%> [...] <% end -%> <% end -%>
If that looks like sacrilegious Rails code to you, then you could consider:
<% objects.each do |object| -%> <% fields_for "object[]", object do |subfield| -%> [...] <% end -%> <% end -%>
In either case, params[:object] will be a hash where the ID of each object (determined via ActiveRecord::Base#to_param ) is associated with a hash of its new values:
params = { 'object' => { '123' => { 'field' => 'newval' }, '159' => { 'field' => 'newval' } } }
![Default_avatar_30](https://www.gravatar.com/avatar/0c2112f6aeafaf03a7fb1bbb8ce090f6?default=http://apidock.com/images/default_avatar_30.png&size=30)
Reloading memoized values
Memoize is used to cache the result of a method. It’s roughly equivalent of having:
def memoized_method(*args) @result[args] ||= ( # do calculation here ) end
However, the result is cached so that it’s not calculated for every request.
To recalculate cached value use either
obj.memoized_method(:reload)
or
obj.memoized_method(true)
![Default_avatar_30](https://www.gravatar.com/avatar/855c677aca7319a44da19fb583b9f320?default=http://apidock.com/images/default_avatar_30.png&size=30)
Javascript encoding DOES work!
grosser assertion is false :
mail_to('xxx@xxx.com', nil, :encode => :javascript) # => "<script type=\"text/javascript\">eval(unescape('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%78%78%78%40%78%78%78%2e%63%6f%6d%22%3e%78%78%78%40%78%78%78%2e%63%6f%6d%3c%2f%61%3e%27%29%3b'))</script>"
Use “nil” as the second parameter to tell mail_to that you want to use the first parameter for both text and email link
![Default_avatar_30](https://www.gravatar.com/avatar/175b1b15a0ae5a8a690479641ad8ac5a?default=http://apidock.com/images/default_avatar_30.png&size=30)
Remember to mixin the ActiveSupport::Memoizable module
To use memoize in your model you need to extend the model class with the module, like this:
class Person < ActiveRecord::Base # Mixin the module extend ActiveSupport::Memoizable def expensive_method # do something that is worth remembering end memoize :expensive_method end
If you use memoizable in most of your models you could consider mixing the module into all ActiveRecord models by doing this in an initializer:
ActiveRecord::Base.extend(ActiveSupport::Memoizable)
![Default_avatar_30](https://www.gravatar.com/avatar/174330d280860a6ad77a6d15dd7fabe1?default=http://apidock.com/images/default_avatar_30.png&size=30)
![Default_avatar_30](https://www.gravatar.com/avatar/1b2792536d87aa21bc739c14980fa103?default=http://apidock.com/images/default_avatar_30.png&size=30)
Convert String to Class in Rails
ncancelliere gave us a very useful tip below, and I just want to make an addendum for it:
If you are using Rails, there is a CoreExtension for this called String#constantize.
"Foo::BarKeeper".constantize #=> Foo::BarKeeper
You can use it with String#camelize if you have to convert the name too
"foo/bar_keeper".camelize #=> "Foo::BarKeeper" "foo/bar_keeper".camelize.constantize #=> Foo::BarKeeper
Don’t forget to rescue NameError in case there was an invalid class name. :-)
![Default_avatar_30](https://www.gravatar.com/avatar/5866464ebc16b5c4729fff4fe7d8fbe7?default=http://apidock.com/images/default_avatar_30.png&size=30)
constantize
@ncancelliere - Instead use constantize which is provided as part of ActiveSupport. It is much easier. So:
mystring.constantize
![Default_avatar_30](https://www.gravatar.com/avatar/d57f8a6095df6b8a3aae2eeae014ccee?default=http://apidock.com/images/default_avatar_30.png&size=30)
Convert String to Class
this example shows how you can take a string and # make it a class and then send it a method
Kernel.const_get(my_string.capitalize).select_options
![Default_avatar_30](https://www.gravatar.com/avatar/d57f8a6095df6b8a3aae2eeae014ccee?default=http://apidock.com/images/default_avatar_30.png&size=30)
Convert String to Class
this example shows how you can take a string and make it a class and then send it a method
Kernel.const_get(my_string.capitalize).select_options
![Default_avatar_30](https://www.gravatar.com/avatar/f4f96a08152550e603ee595403f3ba57?default=http://apidock.com/images/default_avatar_30.png&size=30)
See #data_select for available options
Available symbols for “options” hash are described on date_select page
![Default_avatar_30](https://www.gravatar.com/avatar/56b4f519148bc81868d714aef2cd889a?default=http://apidock.com/images/default_avatar_30.png&size=30)
File open permissions
Usage: File.open path, flags, [permissions]
Flags (bitmasks)
Access:
File::RDONLY |
Read-only |
File::WRONLY |
Write-only |
File::RDWR |
Read and write |
If the file exists:
File::TRUNC |
Truncate |
File::APPEND |
Append |
File::EXCL |
Fail |
If the file doesn’t exist:
File::CREAT |
Flags (strings)
r |
File::RDONLY |
r+ |
File::RDWR |
w |
File::WRONLY|File::TRUNC|File::CREAT |
a |
File::WRONLY|File::APPEND|File::CREAT |
Examples
File.open path, File::RDONLY File.open path, 'w' File.open path, File::WRONLY|File::TRUNC|File::CREAT File.open path, File::WRONLY|File::TRUNC|File::CREAT, '0666'
![Default_avatar_30](https://www.gravatar.com/avatar/5866464ebc16b5c4729fff4fe7d8fbe7?default=http://apidock.com/images/default_avatar_30.png&size=30)
Easier Universal Partials
@hosiawak provides a great example of how to use polymorphic_path to produce universal partials. You can actually simply his example even more with the following:
<%= link_to 'Edit', edit_polymorphic_path(obj) %> <%= link_to 'Delete', obj, :method => :delete %>
So the things to note are that in addition to polymorphic_path, Rails also provides an “edit_” version just like on your resources so you can use that instead of specifying the action specifically. The second thing to remember is if you pass just the raw object as the path then then rails will automatically wrap it in a call to polymorphic_path.
![Default_avatar_30](https://www.gravatar.com/avatar/8cb2fab8fddc8626073f40f0106c0077?default=http://apidock.com/images/default_avatar_30.png&size=30)
Universal partial
polymorphic_url is very useful if you want to create an universal partial that works for more than 1 type of object passed to it.
For example in you sidebar you might have a _sidebar.html.erb partial that’s supposed to display links to “Edit” and “Delete” actions. You can write it in such a way that it can be reused for different types of objects (in the example below we pass either a Post or a Note).
your_template.html.erb
<%= render :partial => 'shared/sidebar', :locals => { :obj => Post.new -%>
other_template.html.erb
<%= render :partial => 'shared/sidebar', :locals => { :obj => Note.new -%>
_sidebar.html.erb
<%= link_to "Edit", polymorhpic_url(obj, :action => 'edit') -%> <%= link_to "Delete", polymorphic_url(obj), :method => :delete -%>
![Default_avatar_30](https://www.gravatar.com/avatar/1b2792536d87aa21bc739c14980fa103?default=http://apidock.com/images/default_avatar_30.png&size=30)
A word of warning
This method returns the supplied string with double quotes around it if it has a space in it, otherwise leaves it alone.
This is useful when sending paths to the shell or any similar operations. Here is a small demonstration of how it works and why it would be useful:
def cat(term) puts "cat #{term}" end def cat_q(term) puts "cat #{term.quote}" end # No difference without whitespace cat "hello.txt" #=> cat hello.txt -- OK! cat_q "hello.txt" #=> cat hello.txt -- OK! # With whitespace cat "hello world.txt" #=> cat hello world.txt -- Error # trying to find "hello" or "world.txt" cat_q "hello world.txt" #=> cat "hello world.txt" -- OK!
Watch out if you want to do things securely, since this method does not escape quotes that are already there!
cat_q 'Peter "Smiley" McGraw.txt' #=> cat "Peter "Smiley" McGraw.txt" -- ERROR!
It is possible to insert fork bombs and other dangerous stuff by taking advantage of this, and that might take down the whole machine, steal data or delete data depending on the rights of the user executing the script.
The insecurity might also transfer into other areas in case you are not using this method for the shell, but for something else.
Please do note that most of these problems can be avoided if you just split the arguments in Ruby when doing system calls, which is easier to do most of the time.
quoted_files = file_list.collect { |f| f.quote } system("grep #{search.quote} #{quoted_files.join(' ')}") system("grep", search, *file_list) # Much easier!
So, in summary: You should only use this method if you know what you’re doing! It’s neither secure nor needed in most (but not all) cases.
![Default_avatar_30](https://www.gravatar.com/avatar/174330d280860a6ad77a6d15dd7fabe1?default=http://apidock.com/images/default_avatar_30.png&size=30)
link_to some url with current params
Code example
link_to "some text", users_path(:params => params, :more_params => "more params")
![Default_avatar_30](https://www.gravatar.com/avatar/2101d75ccd71c5dfb984991a7ba53b9b?default=http://apidock.com/images/default_avatar_30.png&size=30)
Adding params to generated url
Whenever you want to append custom parameters to a to be generated url it might be necessary to stop url_for from escaping.
url_for(:action => 'some_action', :custom1 => 'some_value', :custom2 => 'some_value', :escape => false)
If the escape => false option is not passed the generated url contains & instead of the correct &-sign.
![Default_avatar_30](https://www.gravatar.com/avatar/174330d280860a6ad77a6d15dd7fabe1?default=http://apidock.com/images/default_avatar_30.png&size=30)
![Default_avatar_30](https://www.gravatar.com/avatar/1b2792536d87aa21bc739c14980fa103?default=http://apidock.com/images/default_avatar_30.png&size=30)
Refactoring excessive code for selects
@garg: It is not recommended to have excessive code in the views. You should refactor your code a bit.
<%= f.select(:manufacturer_id, Manufacturer.find(:all).collect {|u| [u.name, u.id]}, :prompt => 'Select') %>
could be changed to this:
# in app/helpers/manufacturer_helper.rb def manufacturers_for_select Manufacturer.all.collect { |m| [m.name, m.id] } end # in the view <%= f.select(:manufacturer_id, manufacturers_for_select, :prompt => 'Select') %>
I would look into collection_select though:
<%= f.collection_select(:manufacturer_id, Manufacturer.all, :id, :name, :prompt => 'Select') %>
It’s much more clean and you don’t have to define a helper for it to be readable (altough it’s still quite long).
If you have to do this often, you should define a FormBuilder extension, so you get methods like f.manufacturer_select:
<%= f.manufacturer_select(:manufacturer_id, Manufacturer.all) %>
IMO, most projects should have a custom form builder anyway, so the addition would be very small. This is my personal opinion, so you don’t have to listen to it. :-)
![Default_avatar_30](https://www.gravatar.com/avatar/1b2792536d87aa21bc739c14980fa103?default=http://apidock.com/images/default_avatar_30.png&size=30)
Watch out for syntax errors
Watch out when you are using returning with hashes. If you would write code like
def foo(bars) returning {} do |map| bars.each { |bar| map[bar.first] = bar } end end
you will get a syntax error since it looks like you tried to supply two blocks! Instead you should write it with parenthesis around the hash:
def foo(bars) returning({}) do |map| bars.each { |bar| map[bar.first] = bar } end end
![Default_avatar_30](https://www.gravatar.com/avatar/5866464ebc16b5c4729fff4fe7d8fbe7?default=http://apidock.com/images/default_avatar_30.png&size=30)
Alternative force initial value
@Bounga - Thanks for the suggestion. Didn’t know about that method. An alternative method I have used is just to assign the default value to the object in your controller. For example your “new” action might now look like:
def new @ecard = Ecard.new params[:ecard] @ecard.sender ||= 'contact@host.com' end
![Default_avatar_30](https://www.gravatar.com/avatar/5866464ebc16b5c4729fff4fe7d8fbe7?default=http://apidock.com/images/default_avatar_30.png&size=30)
Replace allowed tags/attributes
The docs above state how to add and remove tags from the default list. But what if you just want to replace the entire list with a list of your own? You can easily do that with the following code:
ActionView::Base.sanitized_allowed_tags.replace %w(strong em b i hr br ul ol li blockquote) ActionView::Base.sanitized_allowed_attributes.replace %w(href)
Note that if you put this in your initialization block you must use the config.after_initialize hack (to override the default that will be set) but if you put it in an initializer (i.e. a file in the initializers directory) that code is executed after Rails initialization so no need to use any hack. Just use the code above.
![Default_avatar_30](https://www.gravatar.com/avatar/5866464ebc16b5c4729fff4fe7d8fbe7?default=http://apidock.com/images/default_avatar_30.png&size=30)
Default allowed tags and attributes
I found it a bit hard to find the default tags and attributes in the docs.
As of Rails 2.2.2 they are:
Tags
del, dd, h3, address, big, sub, tt, a, ul, h4, cite, dfn, h5, small, kbd, code, b, ins, img, h6, sup, pre, strong, blockquote, acronym, dt, br, p, div, samp, li, ol, var, em, h1, i, abbr, h2, span, hr
Attributes
name, href, cite, class, title, src, xml:lang, height, datetime, alt, abbr, width
Getting the latest list
You can query for this list yourself with the following code on the console:
>> puts helper.sanitized_allowed_tags.to_a * ", " ... will output tag list ... >> puts helper.sanitized_allowed_attributes.to_a * ", " ... will output attribute list ...
The same principal can probably be applied to sanitize_css.
![Default_avatar_30](https://www.gravatar.com/avatar/eca15b2b601e7e577d38bd5210a753ac?default=http://apidock.com/images/default_avatar_30.png&size=30)
What to use instead
For versions 2.0+, use ActiveRecord::Base::sanitize_sql_array
![Default_avatar_30](https://www.gravatar.com/avatar/7fe73b5d5a08f4de9374840fb7d79702?default=http://apidock.com/images/default_avatar_30.png&size=30)
current_action? and current_controller?
I use them in link_unless_current_controller helper.
def current_action?(options) url_string = CGI.escapeHTML(url_for(options)) params = ActionController::Routing::Routes.recognize_path(url_string, :method => :get) params[:controller] == @controller.controller_name && params[:action] == @controller.action_name end def current_controller?(options) url_string = CGI.escapeHTML(url_for(options)) params = ActionController::Routing::Routes.recognize_path(url_string, :method => :get) params[:controller] == @controller.controller_name end
![Default_avatar_30](https://www.gravatar.com/avatar/5866464ebc16b5c4729fff4fe7d8fbe7?default=http://apidock.com/images/default_avatar_30.png&size=30)
link_to_if for named routes
Back before named routes we used to say things like:
<%= link_to_if message.user, 'Poster', :controller => 'users', :action => 'show', :id => message.user %>
This would make the text “Poster” only link if message has a user. But with named routes this has become more complicated. Our first try is something like:
<%= link_to_if message.user, 'Poster', user_path(message.user) %>
Although this looks nice it causes an error since the path is generated prior to the condition not after the condition like using a hash is done. To get around this problem I have found two solutions:
-
If you are linking to the “show” path then you can just pass the object. This will force the path to not be generated until after the condition (like a hash is done). For example:
<%= link_to_if message.user, 'Poster', message.user %>
-
The previous workaround works great if you want to link to the show action. But what if you want to link to another action (say the edit action). In this case the best way I have found is to use the hash_for* helpers generated with the routing resource. So:
<%= link_to message.user, 'Poster', hash_for_edit_user_path(:id => message.user) %>
A little more awkward than the previous workaround but it is the best I can come up with. Any other suggestions (other than going back to manually typing the hash)?