
dm-sweatshop: associations not in order after generation
Reported by phatmann | November 24th, 2008 @ 07:29 PM
After a model is generated, its associated records do not respect the order specified in association declaration. Here is some code to demonstrate the problem:
gem 'dm-core'
gem 'dm-sweatshop'
require 'dm-core'
require 'dm-sweatshop'
class Target
include DataMapper::Resource
property :id, Serial
has n, :matches, :order => [:score]
end
class Match
include DataMapper::Resource
property :id, Serial
property :score, Float
belongs_to :target
end
Match.fixture {{
:score => rand
}}
Target.fixture {{
:matches => 10.of {Match.gen}
}}
DataMapper.setup(:default, "sqlite3://dm_test.db")
DataMapper.auto_migrate!
target = Target.gen
scores = target.matches.map {|m| m.score}
print scores == scores.sort ? "sorted\n" : "unsorted\n"
target.reload
scores = target.matches.map {|m| m.score}
print scores == scores.sort ? "sorted\n" : "unsorted\n"
The workaround is to reload the model, but this is easy to forget to do, especially since dm-sweatshop hides the fact that the associated records were added via the "<<" operator.
On fix is to have #generate reload the model before it returns. The other fix is to generate the associations in a way that DM will not cache them:
10.times {Match.create(:target_id => target.id, :score => rand)}
Comments and changes to this ticket
-
Dan Kubb (dkubb) December 5th, 2008 @ 05:06 AM
- Assigned user changed from Sam Smoot to Xavier Shay
- State changed from new to unconfirmed
Xavier, would you mind looking at this?
-
Xavier Shay December 5th, 2008 @ 04:18 PM
- State changed from unconfirmed to accepted
-
Xavier Shay December 9th, 2008 @ 10:35 AM
We can't use .reload for two reasons:
- It adds a ~30% performance hit, despite being strictly unnecessary most of the time
- It does not work for unsaved fixtures
My next idea is using reflection to detect fixtures being added to a sorted association and sort in code, which of course has its own issues.
This sounds like a whole lot of work + code for an edge case. I'm thinking just put a buyer beware in the README and be done with it.
Thoughts?
-
Please Sign in or create a free account to add a new ticket.
With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »