【Rails3.2】uniqメソッドを使った際に、ActiveRecord::StatementInvalidが発生してしまう場合

Rails3.2から導入されたActiveRecord::Relation#uniq はとっても便利で、

records.select(:name).uniq

と書くだけで、ユニークなnameの一覧が取得できます!
(recordsは何かしらレコードの集合です。)
でも

records = Client.order(:address)
     :
records.select(:name).uniq

と書くと、

ActiveRecord::StatementInvalid: PG::Error: ERROR:  for SELECT DISTINCT, ORDER BY expressions must appear in select list

というようなエラーを吐いてしまいます。
これは、selectしていないカラムに含まれていないカラム(この例ではaddress)でorderしようとしたために発生しています。

この例ではorderを消せば良い話ですが、
他のメソッドからorder済みの値が渡ってくる場合は困ってしまいます。(´・ω・`)
そんな際は、reorder()メソッドを使えば良いです。

records = Client.order(:address)
     :
records.reorder(:name) #それまでのorderをなかったことにして、orderしなおす
records.select(:name).uniq

以上により、selectに含まれないカラムに対するorderを消すことが出来、無事動くようになりました。

update_allメソッドって便利だなー

where()などで必要な複数レコードを抽出しておいて、一括で値変更できます。
ActiveRecord::Relationのメソッドとして実装されてる)

いままでsql直書きしてたよ。。(´・ω・`)
その前は、eachをレコード分実行して値書き換えてたよ。よくないよね。。(´;ω;ω;`)

忘備録的にリファレンスマニュアルのサンプルを貼り付けます。

# Update all customers with the given attributes
Customer.update_all :wants_email => true

# Update all books with 'Rails' in their title
Book.update_all "author = 'David'", "title LIKE '%Rails%'"

# Update all avatars migrated more than a week ago
Avatar.update_all ['migrated_at = ?', Time.now.utc], ['migrated_at > ?', 1.week.ago]

# Update all books that match conditions, but limit it to 5 ordered by date
Book.update_all "author = 'David'", "title LIKE '%Rails%'", :order => 'created_at', :limit => 5

# Conditions from the current relation also works
Book.where('title LIKE ?', '%Rails%').update_all(:author => 'David')

# The same idea applies to limit and order
Book.where('title LIKE ?', '%Rails%').order(:created_at).limit(5).update_all(:author => 'David')

【Ruby】条件分岐をワンライナーで書く

def special_or_normal
  @current_user.special? ? "special" : "normal"
end

special? がtrueならspecialを返却、そうでなければnormalを返却。
?で条件分岐して、 : で分割して列挙する。
以下のコードと同じ。

def special_or_normal
  if(true == @current_user.special?)
     "special"
  else
    "normal"
  end
end

【Rails3】開発中にRailsを再起動しないといけないときは?

RailsはDevelopmentの場合、ブラウザから要求があるたびにクラスを読み込み直してくれるので、Railsを再起動せずとも加えた修正が反映されます(*´ω`*)
でも、下記3ケースの場合は修正が反映されないので要注意です。
(1)config/* が書き換わった場合
(2)lib/* が書き換わった場合
(3)bundle install をした場合(Gemfile.lockが書き換わった場合)
ついつい忘れがちな人は、上記ファイルが書き換わったら自動で再起動してくれるguard_railsが便利かもしれないですね!
https://github.com/johnbintz/guard-rails

【Javascript】PhantomJSで簡単スクレイピング

http://code.google.com/p/phantomjs/
Javascriptで動作する「ヘッドレスブラウザ」
参考URL
http://d.hatena.ne.jp/karasuyamatengu/20110126/1296066287

これをスクレイピングに使ってみます。JQueryも使えて楽しい。
今日はこのPhantomJSを使って、【コマンドライン英和辞典】を作ってみます。
ではソースコード(Coffeescript):

JqPageが親クラスで、JQueryを使ってスクレイピングするための基本機能を提供します。
Alcという小クラスで、英和辞典のアルクさんをスクレイピングします。

#!/usr/bin/env phantomjs                                                                                           

# input check                                                                                                      
if(phantom.args.length == 0)
  console.log('please set url.')
  phantom.exit()

class JqPage
  constructor: (@url) ->
    #@alert(@url)                                                                                                  
    @page = require('webpage').create()
    @page.open(@url, @onOpen)
    return this
  onOpen: (status) =>
    if(status == 'success')
      #@alert('open success')                                                                                      
      @page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", @onLoad)
    else
      @alert('fail')
    return

  onLoad: () =>
    #@alert('jquery loaded')                                                                                       
    phantom.exit()
    return

  alert: (str) ->
    console.log(str)
    return this

class Alc extends JqPage
  constructor: (@query) ->
    @url = "http://eow.alc.co.jp/search?q=" + @query
    super(@url)
  onLoad: () =>
    txt = @page.evaluate ->
      $("#resultsList > ul > li:first").text()
    @alert(txt)
    super()

aa = new Alc(phantom.args[0])

このファイルをalc.coffee として保存し、

$ alc.coffee foo

と入力すると、、、

foo
【1名】=foo dog【2名】《コ》フー◆メタ構文変数名。◆【参考】metasyntactic variable ; foobar

出来たー(*´Д`*)
実質

$("#resultsList > ul > li:first").text()


という一行でデータを引っ張ってこれます。