내 제품 모델에 일부 항목이 포함되어 있습니다
Product.first
=> #<Product id: 10, name: "Blue jeans" >
다른 데이터 세트에서 일부 제품 매개 변수를 가져오고 있지만 이름의 철자에 불일치가 있습니다. 예를 들어, 다른 데이터 세트에서 Blue jeans
철자를 지정할 수 있습니다 Blue Jeans
.
하고 싶었지만 Product.find_or_create_by_name("Blue Jeans")
첫 번째 제품과 거의 동일한 새 제품을 만들 것입니다. 소문자 이름을 찾아 비교하려면 내 옵션은 무엇입니까?
성능 문제는 여기서 중요하지 않습니다. 100-200 개의 제품 만 있으며 데이터를 가져 오는 마이그레이션으로이 제품을 실행하려고합니다.
어떤 아이디어?
답변
아마 여기서 더 장황해야 할 것입니다.
name = "Blue Jeans"
model = Product.where('lower(name) = ?', name.downcase).first
model ||= Product.create(:name => name)
답변
이것은 내가 참조 할 수 있도록 Rails의 완전한 설정입니다. 도움이된다면 기쁘다.
쿼리 :
Product.where("lower(name) = ?", name.downcase).first
유효성 검사기 :
validates :name, presence: true, uniqueness: {case_sensitive: false}
색인 ( Rails / ActiveRecord? 에서 대소 문자를 구분하지 않는 고유 색인의 답변 ) :
execute "CREATE UNIQUE INDEX index_products_on_lower_name ON products USING btree (lower(name));"
첫 번째와 마지막을 수행하는 더 아름다운 방법이 있었으면 좋겠지 만 다시 Rails와 ActiveRecord는 오픈 소스입니다. 우리는 불평해서는 안됩니다. 우리는 직접 구현하고 풀 요청을 보낼 수 있습니다.
답변
Postegres and Rails 4+를 사용하는 경우 CITEXT 열 유형을 사용하는 옵션이 있으므로 쿼리 논리를 작성하지 않고도 대소 문자를 구분하지 않는 쿼리를 사용할 수 있습니다.
마이그레이션 :
def change
enable_extension :citext
change_column :products, :name, :citext
add_index :products, :name, unique: true # If you want to index the product names
end
그리고 그것을 테스트하려면 다음을 기대해야합니다.
Product.create! name: 'jOgGers'
=> #<Product id: 1, name: "jOgGers">
Product.find_by(name: 'joggers')
=> #<Product id: 1, name: "jOgGers">
Product.find_by(name: 'JOGGERS')
=> #<Product id: 1, name: "jOgGers">
답변
다음을 사용할 수 있습니다.
validates_uniqueness_of :name, :case_sensitive => false
기본적으로 설정은 : case_sensitive => false이므로 다른 방법으로 변경하지 않은 경우이 옵션을 작성할 필요도 없습니다.
http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#method-i-validates_uniqueness_of 에서 자세한 내용을 확인하십시오.
답변
postgres에서 :
user = User.find(:first, :conditions => ['username ~* ?', "regedarek"])
답변
몇 가지 의견은 예제를 제공하지 않고 Arel을 나타냅니다.
대소 문자를 구분하지 않는 검색의 Arel 예는 다음과 같습니다.
Product.where(Product.arel_table[:name].matches('Blue Jeans'))
이 유형의 솔루션의 장점은 데이터베이스에 구애받지 않는다는 것입니다. 현재 어댑터에 올바른 SQL 명령을 matches
사용 ILIKE
합니다 (Postgres 및 LIKE
기타 모든 것에 사용).
답변
SQLite 문서 에서 인용 :
다른 모든 문자는 자체 또는 대소 문자가 일치합니다 (예 : 대소 문자를 구분하지 않음)
… 몰랐지만 작동합니다 :
sqlite> create table products (name string);
sqlite> insert into products values ("Blue jeans");
sqlite> select * from products where name = 'Blue Jeans';
sqlite> select * from products where name like 'Blue Jeans';
Blue jeans
따라서 다음과 같이 할 수 있습니다.
name = 'Blue jeans'
if prod = Product.find(:conditions => ['name LIKE ?', name])
# update product or whatever
else
prod = Product.create(:name => name)
end
아니 #find_or_create
, 나는 알고 있으며 데이터베이스 간 매우 친숙하지는 않지만 볼 가치가 있습니까?