Hi Neil >From the sequence of events you've described below, it seems the problem is that one of your updates of the existing children is updating the record id too and putting that beyond the end of the sequence. Or that one of your create_child_from(data) calls is creating a record with the same. DataMapper doesn't stop you from doing this, as it's valid in SQL, and the authors assume if you want to do it, you have good reason.
In terms of documentation being dated, I wouldn't worry too much. DataMapper takes the stability of its API /very/ seriously. The public behaviour of the save() and update() methods definitely hasn't changed since 1.0.0 was released (in 2010) and was pretty stable for a long time before that. As for a more 'elegant' way of doing this, I'm not sure that there is one. Wrapping the whole thing in a transaction might improve your storage efficiency a little bit. Also, looking more toward the future, updating all the attributes via "resource.attributes = new_values" and then triggering the update process with a save of the parent right at the end might allow an adapter to generate a large sql call instead of lots of little ones, but that's hypothetical. Regards Jonathan On 15 January 2012 04:05, Neil Chaudhuri <[email protected]> wrote: > Hey Jonathan, > > Assume I have a Parent instance fetched from the database (Postgres) > and it has some existing Child instances (as the Parent and Child > instances were all created at the same time). The first thing I did is > call > > existing_parent.update(new_parent_values) > > ...which updates values in the Parent instance but nothing related to > the children. > > Then to update the children I did this > > existing_parent.children.each do |child| > updated = child.update( { #values }) > end > > ...which makes some changes to the existing children that are > persisted just fine. > > Then I want to add a NEW child to the children collection, which I did > this way > > existing_parent.children << create_child_from(data) > #create_child_from(data) creates a new Child instance in memory and > populates it with data > existing_parent.save > > It is on this third operation where I get the sequence error. > > Executing the reset sequence statement beforehand does indeed help, so > that solves the problem technically. > > I would still love to know if there is a more efficient or elegant way > to do the same sort of thing--in fact, for all the operations of > updating the parent, then updating the existing children, then adding > a brand new child. The documentation I've been reading seems a bit > dated. > > Thanks. > > > On Jan 14, 8:39 am, Jonathan Stott <[email protected]> wrote: >> Hi Neil >> >> Errors like that tend to occur if you've imported a whole bunch of >> pre-existing records into the database/table without updating the >> sequence. Ideally you should never need to run it, but if you have >> to, the time to do it is just after you've performed the DB import >> task. If you haven't just done that, can you explain what you did >> before the errors occured? >> >> I'm not sure DataMapper has any explicit support for this. >> >> Regards >> Jonathan >> >> On 14 January 2012 00:54, Neil Chaudhuri <[email protected]> wrote: >> >> >> >> >> >> >> >> > Apparently, the reason why updates won't save is a sequence issue as >> > found >> > here:http://railspikes.com/2009/3/6/duplicate-key-violates-unique-constraint >> >> > So I suppose I need to do something like this: select >> > setval('children_id_seq', (select max(id) + 1 from children)); >> >> > I have two questions as I am not a DBA: >> >> > 1) When exactly do I do this? Every time I want to insert a child >> > record? >> > 2) Why doesn't DataMapper handle this? Maybe I am spoiled by using >> > Hibernate in the Java world, but they handle sequences fairly easily >> > by using what they call dialects. I assumed the database-specific >> > DataMapper gems would do something similar. Or maybe they do and I am >> > just missing it? >> >> > Thanks. >> >> > On Jan 13, 1:14 pm, Neil Chaudhuri <[email protected]> wrote: >> >> I have been able to create a 1:M relationship using DataMapper and >> >> update the child items as well after creation. However, I have been >> >> unable to add to that collection. >> >> >> Let's say I have >> >> >> class Parent >> >> include DataMapper::Resource >> >> >> property :id, Serial >> >> ... >> >> >> has n, :children >> >> end >> >> >> class Child >> >> include DataMapper::Resource >> >> >> property :id, Serial >> >> ... >> >> belongs_to :parent >> >> end >> >> >> Whenever I try to add to the child collection belonging to a certain >> >> parent instance, I get either DataMapper::UpdateConflictError or >> >> "DataObjects::IntegrityError: ERROR: duplicate key value violates >> >> unique constraint "children_pkey" DETAIL: Key (id)=(1) already >> >> exists. >> >> >> I have tried a whole host of approaches. The most promising seemed >> >> parent.children.create(attributes), but that led to the >> >> IntegrityError. What is the preferred approach for adding a new item >> >> to the collection? >> >> >> Thanks. >> >> > -- >> > You received this message because you are subscribed to the Google Groups >> > "DataMapper" group. >> > To post to this group, send email to [email protected]. >> > To unsubscribe from this group, send email to >> > [email protected]. >> > For more options, visit this group >> > athttp://groups.google.com/group/datamapper?hl=en. > > -- > You received this message because you are subscribed to the Google Groups > "DataMapper" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]. > For more options, visit this group at > http://groups.google.com/group/datamapper?hl=en. > -- You received this message because you are subscribed to the Google Groups "DataMapper" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/datamapper?hl=en.
