Hey Jonathan,

I took a look at what I'm doing with ids, and I don't think I am
messing with ids at all. In my update of the existing children, I
don't update their ids. When I create the new child instance in
memory, I don't give it an id at all because the id property is a
Serial type in my DataMapper model.

I've talked enough, so here is some code:

def self.update_children(parent, children_hash)
    parent.children.each do |child|
      name_to_status_hash = children_hash[child.id.to_s]
      unless name_to_status_hash.nil?
        updated = child.update(
            {
                :status => name_to_status_hash[child.name]
            })
      end
    end
end

where children_hash looks like this:

children_hash = {
        "1"=>{"Bobby"=>"true"},
        "2"=>{"Sue"=>"false"}
}

As you can see, I am iterating through the child collection from the
parent, and for each child's id I am grabbing the value from the
children_hash provided by a controller and updating only the status.
Not touching the id.

Now here is the code for creating a new child:

def self.create_child_from(name)
    child = Child.new
    child.attributes = {
        :name => name
    }
    child
end

Only name is required, so I populate that. But you'll notice no id
value.

So I am still fairly confused. At least the code works with the
sequence reset!

Thanks.


On Jan 15, 5:35 am, Jonathan Stott <[email protected]> wrote:
> 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 
> > 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.

Reply via email to