I am using datamapper in a Sinatra application. I currently use the command
DataMapper.finalize.auto_upgrade!
to handle the migrations. I had two Classes (Artists and Events) with a ‘has_n’ and ‘belongs_to’ association. An Event ‘belonged_to’ one Artist and an Artist could have many Events associated with it.
I changed the association to be a many_to_many relationship by deleting the previous parts of the class definition which governed the original one_to_many association in the models and adding
has n, :artists, :through => Resource
to the Event class and the corresponding code to the Artist class. When I make a new Event, an error is kicked off.
#<DataObjects::IntegrityError: events.artist_id may not be NULL
The :artist_id field is a relic of the original association between the two classes. The new many_to_many association is accessed by event.artists[i] (where ‘i’ is just an integer index going from 0 to the number of associated artists -1). Apparently the original association method between the Artist and Event classes is still there? My guess is the solution to this is to not just use the auto_upgrade method built into datamapper but rather to write an explicit migration. If there is a way to handle this type of change to a database and still have the auto_upgrade method work, that would be great!
If you need more details about my models or anything please ask and I’ll gladly add them.
In my experience, DataMapper’s
auto_upgradedoes not work very well — or, to say the least, it doesn’t work the way I expect it to. If you want to add a new column to your model, it will do what it should; try to do anything more sophisticated to a column and it probably won’t behave as you expect.For example, if you create a property of type
String, it will initially have a length of 50 characters. If you notice that 50 characters is not enough to hold your string, adding:length => 100to the model won’t be enough to makeauto_upgradechange the column’s width.It seems you have stumbled upon another shortcoming, although one may argue that, in your case, maybe DataMapper’s behavior isn’t that bad (think of legacy databases). But the fact is that, when you changed the association, the
Event‘sartist_idcolumn wasn’t removed, and then when you try to save anEvent, you’ll get an error because the database says it is a required field.Notice that the error you are getting is not a validation error: DataMapper thinks everything looks ok, but gets an error from the database when trying to save the object.
Hope this helps!