DataMapper first_or_create doesn't work... any ideas why?
Well, I've finally decided that I'm not crazy. So, that leaves DataMapper.
Here's what I'm doing. I have a model Msrun which has 1
Metric.
tmp = Msrun.first_or_create # I'll skip the boring details
tmp.me开发者_StackOverflow中文版tric = Metric.first_or_create( {msrun_id: tmp.id}, {metric_input_file: @metricsfile} )
p tmp.metric # => #<Metric @metric_input_file=nil @msrun_id=1>
tmp.metric.metric_input_file = @metricsfile
p tmp.metric # => #<Metric @metric_input_file=#<Pathname:/home/ryanmt/Dropbox/coding/rails/metrics_site/spec/tfiles/single_metric.txt> @msrun_id=1>
So, why doesn't this work? I'm reading http://datamapper.org/docs/create_and_destroy and doing what it shows working. This has been terribly arduous. Thanks for any help.
Update:
I still can't figure out what is going on, but to prove I'm not insane...puts Metric.all # => []
tmp.metric = Metric.first_or_create( {msrun_id: tmp.id}, {metric_input_file: @metricsfile} )
puts Metric.all # => [] #??????????????
tmp.metric.metric_input_file = @metricsfile
p tmp.metric # => #<Metric @metric_input_file=#<Pathname:/home/ryanmt/Dropbox/coding/rails/metrics_site/spec/tfiles/single_metric.txt> @msrun_id=1>
tmp.metric.save
puts Metric.all # => [#<Metric @metric_input_file=#<Pathname:/home/ryanmt/Dropbox/coding/rails/metrics_site/spec/tfiles/single_metric.txt> @msrun_id=1>]
So, not only is first_or_create
not delivering on the behavior I expect by reading the source
def first_or_create(conditions = {}, attributes = {})
first(conditions) || create(conditions.merge(attributes))
end
but it is also not even creating.
I'm probably missing something here (more of those boring details might help) but if the metric exists, it's metric_input_file shouldn't be updated, i.e., it's only set when new. If you're after updating then you can do
.first_or_create(msrun_id: tmp.id).update(metric_input_file: @metricsfile)
Or if not hitting the database twice is relevant, then
m = Metric.first_or_new(msrun_id: tmp.id)
[set..save..assign]
But if it's not being set on new models, I don't see what would cause that from the code posted so far, more..?
[UPDATED]
Based on your new code, I'd say this is "a classic case" of a false DM save. I usually add the following line to an initialization section, e.g., application.rb in Rails.
DataMapper::Model.raise_on_save_failure = true
Unfortunately, the exception raised never tells you why (there's a special place in hell for that choice, right next to people who talk in theaters.) But it's typically one of:
- a slightly incorrect association definition
- a has/belongs_to that isn't "required: false" and isn't set
- putting the wrong datatype into a field, e.g., a string into a decimal
- a validation failing
If you want to post your model definitions, the problem may be spottable there.
In addition to the answer above, I've seen this call die (like, literally halt all execution) with no error when I was doing a find_or_create that would have created an object that violated the primary key constraint. This is because the datamapper model was not in sync with the actual database schema.
精彩评论