views:

431

answers:

1

Hi,

I'm have this two classes

class User
   include DataMapper::Resource
   property :id, Serial
   property :name, String

   has n :posts, :through => Resource

end

class Post
   include DataMapper::Resource
   property :id, Serial
   property :title, String
   property :body, Text

   has n :users, :through => Resource
end

So once I have a new post like:

Post.new(:title => "Hello World", :body = "Hi there").save

I'm having serious problems to add and remove from the association, like:

User.first.posts << Post.first #why do I have to save this as oppose from AR?
(User.first.posts << Post.first).save #this just works if saving the insertion later

and how should I remove a post from that association? I'm using the following but definitely its not working:

User.first.posts.delete(Post.first) #returns the Post.first, but nothing happens
User.first.posts.delete(Post.first).save  #returns true, but nothing happpens
User.first.posts.delete(Post.first).destroy #destroy the Post.first, not the association

So I really don't know how to delete this from the BoltUser Array,

Any Help please?

Thank you very much :)


UPDATE: I Managed to do it by doing:

#to add
user_posts = User.first.posts
user_posts << Bolt.first
user_posts.save 

#to remove
user_posts.delete(Bolt.first)
user_posts.save

I think the only way to do it is working with the instance actions, do your changes on that instance and after you finished, just save it. It's kind of different from AR but, its cool though.

I'm not sure if its possible to do it with any other method, but this is fine for now :)

+3  A: 

The delete() method, and other methods from Array only work on the in-memory copy of the Collections. They don't actually modify anything until you persist the objects.

Also, all CRUD actions performed on a collection primarily affect the target. A few, like create() or destroy(), will add/remove the intermediary resources in many to many collections, but it's only a side effect of creating or removing the target.

In your case, if you wanted to remove just the first Post, you could do this:

User.first.posts.first(1).destroy

The User.first.posts.first(1) part returns a collection scoped to only the first post. Calling destroy on the collection removes everything in the collection (which is just the first record) and includes the intermediaries.

dkubb
Thanks for the explanation Dan, this method you've mentioned worked as well! Cheers
ludicco
Isn't create() deprecated? But I understand that new() now functions the same for a collection, so that User.first.posts.new() will create and persist a record?
arbales
No, create() isn't deprecated. new() just initializes the resource in memory. It does however link it to the parent object, so saving the parent will result in the child being saved too.
dkubb