为 API 包装器实现类似 ActiveRecord 的关联
我最近写了 ParseResource,它是 Parse.com 的 REST API。
这是一些基本用法:
class Post < ParseResource
fields :title, :author, :body
end
p = Post.create(:title => "Hello world", :author => "Alan", :body => "ipso lorem")
该项目相当年轻,我真正想要实现的一个功能是关联。像这样的事情:
class Author < ParseResource
has_many :posts
fields :name, :email
end
class Post < ParseResource
belongs_to :author
fields :title, :body
end
a = Author.create(:name => "Alan", :email => "[email protected]")
p = Post.create(:title => "Associated!", :body => "ipso lorem", :author => a)
p.author.class #=> Author
p.author.name #=> "Alan"
a.posts #=> an array of Post objects
我希望任何已经实现了类似功能的人以及任何掌握 Parse 的 REST API 的人提供任何建议、指示和陷阱。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我发现使用 DataMapper ( http://datamapper.org ) 可以很容易地使其与几乎任何数据存储区一起使用。您可以编写一个与数据存储区通信的适配器,然后直接使用 DataMapper 的所有功能,就像您的数据位于 SQL 中一样。这是一个链接,解释了有关编写这些适配器之一的一些信息。 http://www.killswitchcollective.com/articles/55_datamapperabstractadapter_101
I've found using DataMapper ( http://datamapper.org ) it's pretty easy to get it working with almost any datastore. You can write an adapter that talks to your datastore and then use all of the power of DataMapper directly as if your data was in SQL. Here's a link that explains a bit about writing one of these adapters. http://www.killswitchcollective.com/articles/55_datamapperabstractadapter_101
看起来 Parse 的工作原理是将对象存储为键值对的哈希值。所以基本上你有一个 id 和一个哈希值,你可以用它来发挥你的想象力。
要进行像 ActiveRecord 这样的关联,您需要一个主键(例如,Author.id)和一个外键(例如,Post.author_id)。 Author.id 很简单 - 只需将其设为 Parse 对象的 id 即可。然后将帖子的作者 ID 存储在帖子中,以“author_id”为键。这就是数据方面。
在代码中需要考虑多个实现级别。对于检索,您的目标是创建这样的方法:
这并不太难,可以通过多种方式完成,例如使用元编程。更难的是保存。至少从作者的角度来看,您的目标是这样的:
或者更确切地说,我应该说这就是您可能的目标,具体取决于场景。实施关联的陷阱之一是决定何时做某事。您不想让您的生活变得复杂,但您也不想为 API 调用而疯狂。考虑简单地更新作者的姓名:
如所写的
after_save
将加载现有帖子(它会通过设置@posts的posts
),在每个帖子上设置author_id(不需要在这种情况下完成),然后保存帖子,即使它们没有发生任何改变。此外,如果帖子在保存过程中失败怎么办?在这种情况下,需要事务,以便您可以回滚整个事务并防止不一致的状态。您可以在ActiveRecord 代码中看到围绕当父母得救时如何处理孩子的问题有大量的逻辑。结果是光滑而透明的关联,但也涉及到其他各种事情; 代理,关联类等
我的建议是这样的。确定您是否真的需要圆滑且透明的关联。如果没有,那么对一些访问器和便捷方法进行元编程,然后就这样。否则,花时间直接研究 ActiveRecord 关联代码或考虑 DataMapper ,据我所知,它为您提供了一个类似 ActiveRecord 的界面,包括关联,具有更改数据存储的能力。
It looks like Parse works by storing objects as a hash of key-value pairs. So basically you have an id and then a hash with which you can let your imagination run.
To do associations like ActiveRecord you need a primary key (e.g., Author.id) and a foreign key (e.g., Post.author_id). The Author.id is simple - just make it the id of the Parse object. Then store the author id for a post inside the post, keyed by 'author_id'. So that's the data side.
In the code there are several levels of implementation to consider. For retrieval you're aiming to make methods like this:
That's not too hard and can be done in many ways, for instance using metaprogramming. Harder is the save. What you're aiming for, at least from the Author side, is something like this:
Or rather I should say that's what you might be aiming for depending on the scenario. One of the pitfalls in implementing associations is deciding when to do stuff. You don't want to complicate your life, but you also don't want to go crazy with API calls. Consider simply updating the name of an author:
As written
after_save
will load existing posts (it goes throughposts
which sets @posts), set author_id on each post (which need not be done in this case), and then save the posts even though nothing has changed them. Moreover what if a post fails during save? In that case transactions are needed so you can rollback the whole thing and prevent an inconsistent state.You can see in the ActiveRecord code there is a ton of logic surrounding the issue of how to handle children when a parent is saved. The result is the slick and transparent associations but all kinds of other things get involved; proxies, association classes, etc.
My advice is this. Decide if you really need slick and transparent associations. If not then metaprogram a few accessors and convenience methods and leave it at that. Otherwise, spend time studying the ActiveRecord association code directly or consider DataMapper which, AFAIK, gives you an ActiveRecord-like interface, including associations, with the ability to change data stores.