validates_uniqueness_of fails because (1) no index on subject, (2) sqlite3 problem or (3) other?

Hi,

I've got 5 validations on my model. Only one of them fails to perform as expected:

class Portfolio < ActiveRecord::Base   [snip]   validates_uniqueness_of :symbol end

I'm running Rails 2.0.2. I created the app following a couple of very helpful Rails 2.0 newbie tutorials.

I got sqlite3 as the DBMS by default, which I don't know. To solve this, I'm going to try: 1. Adding, using SQL, an index to the Symbol column of the portfolios table in the development.sqlite3 database 2. Switching to MySQL 5.0, which I'm experience with, by regenerating the app with rails -d

Any comments/observations/suggestions welcome.

Thanks in Advance, Richard

RichardOnRails wrote:

Hi,

I've got 5 validations on my model. Only one of them fails to perform as expected:

class Portfolio < ActiveRecord::Base   [snip]   validates_uniqueness_of :symbol end

Hi Richard,

How is it failing? What are you expecting? What is it doing? Is there an error message? What does the migration for portfolios look like?

I think we need a bit more information.

Peace, Phillip

Hi Phillip,

Thanks for expressing an interest in my problem.

What does the migration for portfolios look like?

class CreatePortfolios < ActiveRecord::Migration   def self.up     create_table :portfolios do |t|       t.string :symbol       t.string :name

      t.timestamps     end   end

  def self.down     drop_table :portfolios   end end

How is it failing? What is it doing?

I click on "New portfoilo", enter a three-letter Symbol "XXX" and click "Create". That yields the response "Portfolio was successfully created." and displays the Symbol and Name (the latter being blank). I click "Back" and see the new (XXX) Symbol and its (blank) Name displayed, along with other pairs I've entered.

What are you expecting?

I repeat this process and see another instance of XXX. That' violates the uniqueness declaration in the following specification:

class Portfolio < ActiveRecord::Base   before_save :uppercase_data

  def uppercase_data     self.symbol.upcase!   end

  validates_presence_of :symbol   validates_length_of :symbol, :maximum=>5, :message=>"exceeds %d characters"   validates_uniqueness_of :symbol   validates_format_of :symbol, :with => /^[a-zA-Z\d]+$/, :on => :create,     :message => "(Character other than letter or digit found, e.g a blank)" end

Is there an error message?

No. But there should be an error message indicating the the second XXX could not be added because it's not unique.

Please let me know if there's anything else I can provide.

I'm going to get my personal website under my ISP's aegis re- established so I can just post my code so that any interested party can simply view whatever part he wishesl

Sincerely, Richard

Hi Phillip,

False alarm. I entered the constraint using my favorite editor, SciTE, and failed to save my change :-(. Mea culpa for putting you (and me) to this trouble.

Best wishes, Richard

RichardOnRails wrote:

Hi Phillip,

False alarm. I entered the constraint using my favorite editor, SciTE, and failed to save my change :-(. Mea culpa for putting you (and me) to this trouble.

Best wishes, Richard

On Jun 23, 4:23 pm, Phillip Koebbe <rails-mailing-l...@andreas-s.net>

Richard,

That's okay. I got a good laugh out of it, so it's worth something!

Peace, Phillip

Hi Phillip,

I got a good laugh out of it, so it's worth something!

OK, here’s an opportunity to pay for the humor I provide :slight_smile:

Presently, I report as an error user input for Symbol containing a non-letter or non-digit. I’d like to relax that in the case where the offending characters are merely leading and/or trailing whitespace.

I plan to accomplish this by preceding the constraint:   validates_format_of :symbol, :with => /^[a-zA-Z\d]+$/, :on => :create,     :message => "(Character other than letter or digit found, e.g a blank)" with the following:   parameters[:symbol] =~ /^\s*([A-Za-z0-9])\s*$/   parameters[:symbol] = $1 if $1

I haven’t tried it yet, but I’m a pessimist. If it works, I’ll send you another “false alarm” mea culpa. On the other hand, if you see an error or a more Rails-y way to do this, I’d appreciate hearing from you.

Best wishes, Richard

RichardOnRails wrote:

offending characters are merely leading and/or trailing whitespace.

This is similar to the uppercase problem: why raise an error when you can just do it yourself? Instead of raising an error and telling the user to not use whitespace at the beginning or end of the symbol, why not just get rid of it yourself?

" a string with leading and trailing spaces ".strip => "a string with leading and trailing spaces"

Beyond that, I'm not at all qualified to give any kind of suggestions when it comes to regular expressions. I have looked at them a few times, and have even read some decent tutorial material, but since I don't use them very often, it all goes away very quickly. Just like physics when I was in college.

Peace, Phillip

Hi Phillip,

This is similar to the uppercase problem: why raise an error when you can just do it yourself?

That's precisely what I'm trying to do, i.e strip leading/trailing spaces silently. I've already realized my code is in error by referring to 'parameters' rather than 'params'.

I'm fine with the RE stuff. In case you're interested, I'll explain what the code does and provide a small Ruby program to demo it.

If you're not interested about Ruby regex's, READ NO FURTHER and accept my thanks for your willingness to look ino my problem. BTW, I just posted a question about my "params" stumbling block.

Best wishes, Richard

The expression /^\s*([A-Za-z0-9])+\s*$/ says: ^ Start scanning at the beginning \s match any "whitespace" character, e.g. space, tab, etc. \s* match zero or as many as possible (with some caveats) whitespace characters () match the specification within the parentheses and assign $1 a reference to the matching value [A-Za-z0-9] matches any of the characters A to Z, a to z and 0 to 9, i.e. any of these 62 characters A-Za-z0-9]+ matches one or more of the such characters, as many as possible, with some caveats

So when params[:symbol] (containing the data the user supplied in the textbox labelled Symbol) matches this pattern, then $1 contains the string of legitimate character surrounded front and back by zero or more whitespace characters. If for example, the params[:symbol] contained " AB CD ", this string would NOT match the pattern, so $1 would me nil and my algorithm would leave params unchanged, and the subsequent constraint would flag the entry as invalid.

But if the parms[:symbol] contained " ABCD ", that string would be replaced with "ABCD" and the subsequent constraint would be satisfied.

Here's a Ruby example:

RichardOnRails wrote:

Hi Phillip,

That's precisely what I'm trying to do, i.e strip leading/trailing spaces silently.

Have you looked into String#gsub? You can feed it a regex for the pattern, so you should be able to easily take out all characters that aren't in the 62 acceptable ones.

http://www.ruby-doc.org/core-1.8.6/index.html

Peace, Phillip

Hi Phillip,

I just noticed this addition suggestion made last week.

I did know about String#gsub but opted in this application not to automatically eliminate embedded blanks (versus leading and trailing blanks). I regard embedded blanks as likely indicative of some other user error beyond the blank itself.

Nevertheless, I appreciate your pointing out something else I might be unaware of.

Best wishes, Richard