Recent notes
RSS feedSetting a custom Content type
The given example seems to be broken. The :mime_type option as well as the [] access on the Mime::Type class are both not working.
The following code allows the custom setting of content types as intended by the original example:
class PostsController < ActionController::Base def show @post = Post.find(params[:id]) respond_to do |format| format.html format.ics { render :text => post.to_ics, :content_type => Mime::Type.lookup("text/calendar") } format.xml { render :xml => @people.to_xml } end end end
To use the memcached gem
If you use the mem_cache_store it will use “memcache-client” to talk to the actual cache. memcache-client is a pure Ruby library that is bundled with rails. There is a Ruby/C library called “memcached” that uses native bindings to talk to memcache, and it is reportedly (http://blog.evanweaver.com/files/doc/fauna/memcached/files/README.html) up to a 100 times faster than memcache-client. To use that instead,
# in shell $ sudo gem install memcached --no-rdoc --no-ri # in config/production.rb require 'memcached' config.action_controller.cache_store = :mem_cache_store, Memcached::Rails.new("localhost:11211")
This feature (to pass a configured MemCache-like object to cache_store=) is available since rails 2.3.3 and will hopefully be documented in 2.3.5.
Don't forget to require 'tmpdir'
If you simply say Dir.tmpdir you might get a nice surprise:
irb> Dir.tmpdir NoMethodError: undefined method `tmpdir' for Dir:Class
from (irb):1
Strangely, this method seems to be stored in a file that Ruby doesn’t require by default. Just require 'tmpdir' and all should be well.
irb> require 'tmpdir' => true irb> Dir.tmpdir => "/var/folders/An/AnwlXPZFH2aRLCERERQDKE+++TI/-Tmp-"
How FormBuilders work
What, you were expecting documentation? :)
An excellent survey of how FormBuilders work is here:
http://code.alexreisner.com/articles/form-builders-in-rails.html
Map-like Manipulation of Hash Values
Let’s say you want to multiply all values of the following hash by 2:
hash = { :a => 1, :b => 2, :c => 3 }
You can’t use map to do so:
hash.map {|k, v| v*2 } # => [6, 2, 4]
However, with merge you can:
hash.merge(hash) {|k,v| v*2 } => {:c=>6, :a=>2, :b=>4}
(The above is Ruby 1.8, in Ruby 1.9 the order is preserved.)
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?
Only works within a transaction
Of course, this has to be done in a transaction, like so:
# we've loaded user earlier and did some checks which took some time # to make sure, updates made meanwhile by other threads don't lead to # optimistic locking errors here, we do this when finally suspending User.transaction do user.lock! user.suspended = 1 user.save! end
Setting child_index while using nested attributes mass assignment with prototype
First of all, drogus idea really helped me. I’m not using jQuery, therefore I implemented my own version:
link_to_function
def add_object_link(name, where, render_options) html = render(render_options) link_to_function name, %{ Element.insert('#{where}', #{html.to_json}.replace(/index_to_replace_with_js/g, new Date().getTime())); } end
Using add_object_link
<%= add_object_link 'Add asset', 'assets', :partial => 'assets/asset', :object => Asset.new, :locals => { :f => f } %>
Update statement won't include all attributes with ActiveRecord::Dirty
With the addition of ActiveRecord::Dirty, the update statement will only feature changed columns, as opposed to the comment of railsmonk below.
See Dir#glob
See glob for more usage information and comments.
Getting relative path from absolute globbing
Say you want to scan for files in directory base_dir and you want to use the relative path from this base dir, you could do it like this:
base_dir = '/path/to/dir' files = Dir[File.join(base_dir, '**', '*.yml')] # files now contain absolute paths: files.first # => "/path/to/dir/foo/bar.yml" # let's make them relative base_pathname = Pathname.new(base_dir) files = files.collect do |file| Pathname.new(file).relative_path_from(base_pathname) end files.first # => "foo/bar.yml"
Of course, a more common use-case could be the following:
def scan_for_documents! base_path = Pathname.new(self.base_path) self.contained_files = [] Dir[File.join(self.base_path, '**', '*.pdf')].each do |full_path| path = Pathname.new(full_path).relative_path_from(base_path) self.contained_files << path end end
Get all inner texts
Extend REXML::Element so that it can get the first text and following inner texts (child texts included) of the current element as array and as string:
class REXML::Element def inner_texts REXML::XPath.match(self,'.//text()') end def inner_text REXML::XPath.match(self,'.//text()').join end end
Receiving data over UDP
It’s perfectly normal to receive ‘X’ strings with Ruby’s UDP sockets before the actual content.
Consider the following example:
require 'socket' PORT = 5500 socket = UDPSocket.new socket.bind('', PORT) for i in 1..10 IO.select([socket]) p socket.recvfrom_nonblock(4096) end
Now, sending data with netcat:
echo "Hello APIdock" | nc -vv -u 127.0.0.1 5500
The application would output:
["X", ["AF_INET", 61755, "localhost", "127.0.0.1"]] ["X", ["AF_INET", 61755, "localhost", "127.0.0.1"]] ["X", ["AF_INET", 61755, "localhost", "127.0.0.1"]] ["X", ["AF_INET", 61755, "localhost", "127.0.0.1"]] ["Hello APIdock\n", ["AF_INET", 61755, "localhost", "127.0.0.1"]]
Re: Passing parameters to before_filter
I am not sure I get your “method 1” alec-c4; won’t that define the method each time the before_filter is called? Why not just define the method in the controller?
You can pass parameters or call protected methods with instance_eval:
before_filter :only => :show do |controller| controller.instance_eval do redirect_to edit_object_path(params[:id]) end end
No numbers or symbols
“Kyle”, “Дети”, “Niños”, “Quan-lu”, “た ち”
validates_format_of :first_name, :with => /^([^\d\W]|[-])*$/
Have check_box checked by default
In addition to comment below, you can make a column with default value so in your forms it will be enabled by default and behave correctly with validation errors unlike :checked => true
in your migration
add_column :accounts, :ssl_enabled, :boolean, :default => 1
Current version
See ActiveSupport::Memoizable for un-deprecated version.
build_association deletes existing dependent record
Surprisingly (at least I was surprised), when an associated record exists, the build_association method immediately NULLs the foreign key in the database.
So if you write a singleton “new” action for the association in the obvious way (calling build_association), then just visiting the page will disconnect an existing associated record. This violates the principle that a GET request shouldn’t affect the database.
To avoid this, you can check for an existing association first, and redirect to the show action.
Use it to solve FixtureClassNotFound errors.
If you are using a non standard table name by means of set_table_name in your model:
class MyClassName < ActiveRecord::Base set_table_name "mytablename" end
then you will get FixtureClassNotFound errors when you try to use fixtures in you unit tests. To solve this use set_fixture_class inside your test:
require 'test_helper' class MyClassNameTest < ActiveSupport::TestCase set_fixture_class :mytablename => MyClassName end
and rename your fixture file to mytablename.yml
Case-insensitive comparison
For a case-insensitive comparison, use String#casecmp
Streaming XML with Builder
To generate larger XMLs, it’s a good idea to a) stream the XML and b) use Active Record batch finders.
Here’s one way of doing it:
def my_action @items = Enumerable::Enumerator.new( Item.some_named_scope, :find_each, :batch_size => 500) respond_to do |format| format.xml do render :text => lambda { |response, output| extend ApplicationHelper xml = Builder::XmlMarkup.new( :target => StreamingOutputWrapper.new(output), :indent => 2) eval(default_template.source, binding, default_template.path) } end end end
The Builder template does not need to be modified.
Using argument version in ruby < 1.8.7
The argument to this method was added in Ruby 1.8.7. If you want to use this form in an earlier version, you must instead use the slice! method.
It is mentioned up in the docs, but here it is again for reference:
# Ruby >= 1.8.7 p = list.pop(n) # Ruby < 1.8.7 p = list.slice!(-n, n)
collect/map
If you’d like to use this method for something like Enumerable#collect, you are looking at the wrong place. This method will return the initial integer, not the values from the block.
a = 20.times { |n| n * 2 } #=> 20
Instead, use Range#collect:
a = (0...20).collect { n * 2 }
Use camelize with singular words
To make the business example work, use camelize instead of classify:
"business".camelize # => "Business"