質問

I'm working on an RoR project where I have a model with a string attribute that needs to be entirely case insensitive. I'm just wondering what the best way to do this is.

I've seen some cases where people add setters to their models which uppercase the string before it's put in the database, and I've seen some people that make their queries case insensitive when search the database.

Is there a way to do it on the DB level? I'm using postgres. If not, what's the best way to approach this problem? Does the database take a big hit when searching case insensitive? What about from a security perspective? Is it more secure to check case insensitive every time to prevent problems should someone somehow create a lowercase row? Basically, what is best practice on this?

役に立ちましたか?

解決 2

A db column is never case insensitive. Your interaction may be case insensitive. As you saw, there are several possible cases and solutions.

If the attribute has sense only in a case, but you want to allow searching regardless the case, then always normalize it into a case when writing to the database and filter the queries that access to it. A typical example is an email address. You want to store it always lowercase and make sure to query it in such way, lowering the case of user inputs.

Vice-versa, if in the field you want to save the case is important (such as Title or brand) but you want to allow case insensitive interaction, you have basically two options

  1. Add a separate field that contains the attribute always case insensitive and proceed as in the previous example
  2. Use the database engine functions when you query the database in order to convert the value at runtime. Keep in mind that this will probably prevent the database from being able to use indexes, thus it may result in degraded performances.

他のヒント

There are a number of options you can do:

You can set the local for the database that is case insensitive. Look at pg under Ubunto for an example. This is very OS dependent and tricky. E.g. Mac and RHEL pg is always case sensitive while Ubuntu pg is case insensitive by default. While it has promise, I didn't have much success. The locales installed are OS dependent and I wasn't able to track down a case insensitive local nor information on creating one easily. Installing and distributing the local wasn't trivial. Mysql and SqlServer ship with their own locales while pg uses the OS provided locales. Using their own locales is less flexible and potentially introduces surprises for some languages, but it more consistent across operating systems since the locale is not tied to the operating system.

You can also install the citext extension. Create fields that are citext instead of varchar. Pretty sure extensions make their way into schema.rb now a days. Model.where(:field => "AnY cAsE").

Using ILIKE will perform a case insensitive search as well even if you don't have a wildcard (%). Model.where(Model.arel_table[:field].match("AnY cAsE"))

Create an index on lower(field) and use that to search the table. LIKE vs ILIKE have very different performance characteristics and LIKE tends to be much better. Model.where(Model.arel_table[:field].lower.match("AnY cAsE".downcase, nil, true))

As mentioned above, Store all values as lowercase. Note: This can be in a separate field that is populated in the before_validation callback. Model.where(:field_lower => "AnY cAsE".downcase)

Best of luck. You probably solved this already, but thought I'd share what we've considered at my company for you and others.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top