[Rails] find_or_create_xxx behaving differently than create
It appears that find_or_create_by_xxx is attempting type conversion
where a simple create(...) does not. Bug?
Before going further, here's the schema and the model:
create_table "weather_stations", :force => true do |t|
t.string "callsign"
t.decimal "lat", :precision => 9, :scale => 6
t.decimal "lng", :precision => 9, :scale => 6
t.decimal "elevation_m", :precision => 5, :scale => 1
end
class WeatherStation < ActiveRecord::Base
validates_presence_of :callsign, :lat, :lng
validates_uniqueness_of :callsign, :case_sensitive => false
acts_as_mappable
...
end
[Note the "validates_uniqueness_of :callsign, :case_sensitive => false"
-- that comes into play here.]
** Assume 'specs' is a hash whose :callsign is a string:
>> specs
=> {:callsign=>"0N6", :lat=>39.0128889, :lng=>-75.5339722,
:elevation_m=>15.0}
>> specs[:callsign].class
=> String
** The call to find_or_create_by_callsign fails -- note that id comes
back nil and the other fields are not filled in:
>> w = WeatherStation.find_or_create_by_callsign(specs[:callsign], :lat => specs[:lat], :lng => specs[:lng])
=> #<WeatherStation id: nil, callsign: "0N6", domain: nil, created_at:
nil, updated_at: nil, lat: nil, lng: nil, elevation_m: nil>
** The generated SQL shows a rollback:
WeatherStation Load (22.2ms) SELECT * FROM `weather_stations` WHERE
(`weather_stations`.`callsign` = '0N6') LIMIT 1
SQL (0.4ms) BEGIN
WeatherStation Load (230.6ms) SELECT `weather_stations`.id FROM
`weather_stations` WHERE (LOWER(`weather_stations`.`callsign`) = BINARY
'0n6') LIMIT 1
SQL (1.0ms) ROLLBACK
** Using a simple .create() instead works:
>> x = WeatherStation.create(:callsign => specs[:callsign], :lat => specs[:lat], :lng => specs[:lng])
=> #<WeatherStation id: 30774, callsign: "0N6", domain: nil, created_at:
"2010-05-16 06:38:22", updated_at: "2010-05-16 06:38:22", lat:
#<BigDecimal:8db79b0,'0.390128889E2',12(16)>, lng:
#<BigDecimal:8db7828,'-0.755339722E2',12(16)>, elevation_m: nil>
** ...but looking at the SQL shows that it does the same check for
uniqueness before inserting the row. Since the record isn't in the
table, it's okay that it fails:
SQL (70.0ms) BEGIN
WeatherStation Load (365.4ms) SELECT `weather_stations`.id FROM
`weather_stations` WHERE (LOWER(`weather_stations`.`callsign`) = BINARY
'0n6') LIMIT 1
WeatherStation Create (2.0ms) INSERT INTO `weather_stations`
(`callsign`, `domain`, `created_at`, `updated_at`, `lat`, `lng`,
`elevation_m`) VALUES('0N6', NULL, '2010-05-16 06:38:22', '2010-05-16
06:38:22', 39.0128889, -75.5339722, NULL)
SQL (3.3ms) COMMIT
I don't understand enough about SQL's "BINARY '0n6'" -- is that the
source of the trouble? Or is my validation bogus? Why is
find_or_create_by_callsign() failing?
TIA.
- ff
--
Posted via http://www.ruby-forum.com/.
--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk@googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.

0 Comments:
Post a Comment
Subscribe to Post Comments [Atom]
<< Home