Flowdock

Notes posted by wiseleyb

RSS feed
April 27, 2012 - (>= v3.2.1)
1 thank

Example from Code School

module Tweets

 class ShowPresenter
   extend ActiveSupport::Memoizable

   def initialize(tweet)
     @tweet = tweet
   end

   def username
     @tweet.user.username
   end

   def status
     @tweet.status
   end

   def favorites_count
     @tweet.favorites.count
   end

   memoize :username, :status, :favorites_count

 end
end

From http://railsbest.com/

March 27, 2012 - (>= v3.2.1)
0 thanks

Example to auto download

Controller

op = Operation.find(params[:id])
fname = "operation_#{op.id}_#{DateTime.now.to_i}.csv"
send_data op.export(params[:url_type]), 
  :type => 'text/csv; charset=iso-8859-1; header=present',
  :disposition => "attachment; filename=#{fname}.csv"

export_csv

def export(url_type)
  csv_data = CSV.generate do |csv|
    csv << self.header_columns # simple array ["id","name"]
    url_items = @operation.url_items.where(:url_type => url_type)
    url_items.each do |url_item|
      csv << self.process_row(url_item)  # simple array [1,"bob"]
    end 
  end 
  return csv_data
end
November 7, 2011 - (v3.0.5 - v3.0.9)
1 thank

unscoped.all / unscoped.count

At least in console, doing unscoped.all or unscoped.count initially returns expected results but, after you’ve added new records outside of the default_scope those two calls seem to use some cached values.

Therefore it should always be used with the block (as they sort of imply in the doc). unscoped { all } and unscoped {count }

April 14, 2011
0 thanks

Example

Chops the last character off a string.

> a = "12345"
> a.chop
=> "1234"
> a
=> "12345"
> a.chop!
=> "1234"
> a
=> "1234
April 4, 2011
2 thanks

Working with match captures

Let’s say you wanted to filter out passwords from:

s = "password=bob&password=jim&password=jane"

You’d do this:

r = /password\=([^\&]+)/
s.gsub!(r) { |m| m.gsub!($1, "[FILTERED]") }

Which would return

password=[FILTERED]&password=[FILTERED]&password=[FILTERED]
March 7, 2011 - (>= v3.0.0)
1 thank

:method => :delete, etc.

If you’re upgrading to Rails 3 you’ll need to make sure you include rails.js (which is in public/javascripts when you rails new someproject) You’ll need to include it after prototype. And you’ll need to have a 1.7 version of prototype.

When you do a

link_to "Delete", @some_obj, :method => "delete", :confirm => "Are you sure?"

Rails 3 will generate

<a href="some_obj/id" data-confirm="Are you sure?" data-method="delete">Delete</a>

rails.js will creates observers that convert that into a form.

Be aware that this probably won’t work as a link from inside a form (since forms in forms isn’t valid).

February 10, 2011 - (<= v2.3.8)
2 thanks

Undocumented callbacks

Not sure why this isn’t documented… there are callbacks for before/after_add and before/after_remove. Example

has_many :things, :after_add => :set_things, :after_remove => :remove_things

def set_things(thing)
  ...
end
def remove_things(thing)
  ...
end
February 9, 2011 - (<= v2.3.8)
0 thanks

some gotchas

Works

named_scope :public, :conditions => "public = true"

Works

PUBLIC_CONDITIONS = "public = true"
named_scope :public, :conditions => SomeModel::PUBLIC_CONDITIONS

Works

named_scope :public, lamba { {:conditions => SomeModel.public_conditions} }
def self.public_conditions
  "public = true"
end

Doesn’t work

named_scope :public, :conditions => SomeModel.public_conditions
def self.public_conditions
  "public = true"
end
February 5, 2011 - (<= v2.3.8)
0 thanks

update_all (and delete_all) don't play nicely with default_scope

If you have

class Topic < ActiveRecord::Base
  default_scope :conditions => "forums.preferences > 1", :include => [:forum]
end

and you do a

Topic.update_all(...)

it’ll fail with

Mysql::Error: Unknown column 'forums.preferences' in 'where clause'

The work around for this is:

Topic.send(:with_exclusive_scope) { Topic.update_all(...) }

You can monkey patch this using this code (and requiring it in environment.rb or else where)

module ActiveRecordMixins
  class ActiveRecord::Base
    def self.update_all!(*args)
      self.send(:with_exclusive_scope) { self.update_all(*args) }
    end
    def self.delete_all!(*args)
      self.send(:with_exclusive_scope) { self.delete_all(*args) }
    end
  end
end
end

Then just you update_all! or delete_all! when it has a default scope.

January 5, 2011
0 thanks

Passing in parameters

If you want to pass in parameters you can do it like this:

User.get(:find_by_name, headers = {:name => "bob"})
=> /users/find_by_name.xml?name=bob

For nested routes…

routes.rb

resources :companies do
  resources :users do
    member do
      get :find_by_name
    end
  end
end

In your api code…

class User < ActiveResource::Base  

  self.site = "/companies/:company_id"

  def self.find_by_name(name, company_id)
    User.get(:find_by_name, headers = {:name => name, :company_id => company_id}
  end
end

Then doing…

User.find_by_name("bob", 1)

Would call

companies/1/users/find_by_name.xml?name="bob"

This works in Rails 3.1 - not sure about older versions (specifically I think the routes were done differently in < 3

January 3, 2011
0 thanks

Throw error after rollback

If you want to throw the exception after rolling back you can do something like this:

Company.transaction do
  user.save
  company.save
  x = 1/0
rescue
  exp = $!
  begin
    raise ActiveRecord::Rollback
  rescue
  end
  raise exp
end
January 3, 2011
1 thank

Rollback

To rollback the transaction

transaction do
  unless user.save && company.save
     raise raise ActiveRecord::Rollback
  end
end

Or - catch anonymous exceptions, roll back and re-throw error

transaction do
  user.save
  company.save
  x = 1/0
rescue
  exp = $!
  begin
    raise ActiveRecord::Rollback
  rescue
  end
  raise exp
end
June 13, 2010
0 thanks

Add requires!

Useful for methods that take options = {}

class Hash

def requires!(*params)
  params.each do |param| 
    raise ArgumentError.new("Missing required parameter: #{param}") unless self.has_key?(param) 
  end
end

end
June 13, 2010
0 thanks

keys to/from symbols

There’s probably a more effecient way to do this…

class Hash

def keys_to_strings
  res = {}
  self.keys.each do |k|
    if self[k].is_a?(Hash)
      res[k.to_s] = self[k].keys_to_strings
    else
      res[k.to_s] = self[k]
    end
  end
  return res
end

def keys_to_symbols
  res = {}
  self.keys.each do |k|
    if self[k].is_a?(Hash)
      res[k.to_sym] = self[k].keys_to_symbols
    else
      res[k.to_sym] = self[k]
    end
  end
  return res
end

end
May 11, 2010
1 thank

No Layout, other options

While it renders to the same rules as render, you need to specify params.

You’d think this would work:

render_to_string "users/profile", :layout => false

You need to do this instead

render_to_string(:layout => "users/profile", :layout => false)
March 31, 2010
0 thanks

Always gracefully degrade if JS isn't available

If you always want to degrade when JS isn’t available you can add something like to environment.rb

module ActionView
  module Helpers
    module PrototypeHelper
      def link_to_remote(name, options = {}, html_options = nil)
         html_options ||= {}
         html_options[:href] ||= options[:url]
         link_to_function(name, remote_function(options), html_options || options.delete(:html))
      end
    end
  end
end
February 12, 2010
0 thanks

Example

Delete all files in log

require 'FileUtils'
FileUtils.rm_rf(Dir.glob("log/*"))