Hi Neil

That all looks like it should work.  How did this stuff get into the
DB in the first place, then?  That now seems like the most likely
source of the error.

Also, you can simplify 'create_child_from' somewhat by doing:

def self.create_child_from(name)
  Child.new(:name => name)
end

You could even do this:

parent.children.new(:name => name)

to pre-assign the parent.

Regards
Jonathan

On 15 January 2012 15:42, Neil Chaudhuri <[email protected]> wrote:
> 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.
>

-- 
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