DataMapper has n through Resource DELETE (Remove f

2019-04-12 06:22发布

问题:

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

回答1:

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.



回答2:

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 by 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 it should be fine though.