7

[1]を実行できるようにしたいArtist.case_insensitive_find_or_create_by_name(artist_name)(そして sqlite と postgreSQL の両方で動作させる)

これを達成するための最良の方法は何ですか? 現在、Artistクラスにメソッドを直接追加しているだけです(特に、この機能を別のクラスで使用したい場合は、ちょっと醜いですが、何でも):

  def self.case_insensitive_find_or_create_by_name(name)
    first(:conditions => ['UPPER(name) = UPPER(?)', name]) || create(:name => name)
  end

[1]: 理想的には ですがArtist.find_or_create_by_name(artist_name, :case_sensitive => false)、これを実装するのはかなり難しいようです。

4

4 に答える 4

7

この回答は、質問のコメントで尋ねられた追加の質問に対するものです。

find_or_create_by_nameそのメソッドをオーバーライドすると、デフォルトを呼び出すことができなくなります。ただし、以下に示すように独自に実装できます。

def self.find_or_create_by_name(*args)
  options = args.extract_options!
  options[:name] = args[0] if args[0].is_a?(String)
  case_sensitive = options.delete(:case_sensitive)
  conditions = case_sensitive ? ['name = ?', options[:name]] : 
                                ['UPPER(name) = ?', options[:name].upcase] 
  first(:conditions => conditions) || create(options)
end

これで、オーバーライドされたメソッドを次のように呼び出すことができます。

User.find_or_create_by_name("jack")
User.find_or_create_by_name("jack", :case_sensitive => true)
User.find_or_create_by_name("jack", :city=> "XXX", :zip => "1234")
User.find_or_create_by_name("jack", :zip => "1234", :case_sensitive => true)
于 2010-03-13T17:37:20.777 に答える
5

データベースに基づいてインデックスを作成する必要があります。

postgreSQL

列に小文字のインデックスを作成しartist_nameます。

CREATE INDEX lower_artists_name ON artists(lower(artist_name))

mySQL

検索では大文字と小文字が区別されません

sqlLite

artist_namecollat​​e パラメータを使用して列にインデックスを作成する

CREATE INDEX lower_artists_name ON artists( artist_name collate nocase)

DB に依存しない方法で find_or_create を使用できるようになりました。

find_or_create_by_artist_name(lower(artist_name))

参照

PostgreSQL: 大文字と小文字を区別しない検索

sqlLite: 大文字と小文字を区別しない検索

于 2010-03-12T21:22:21.973 に答える
1

ここでこれについて話しました。誰もあなたよりも優れた解決策を思い付くことができませんでした:)

于 2010-03-12T21:02:24.543 に答える