在 Ruby/Rails 中隔离数据访问层的最佳实践

发布于 2024-10-18 02:30:02 字数 473 浏览 1 评论 0原文

所以,我有 Ruby on Rails 应用程序。暂时空白。让我从一开始就说,我的大部分经验都来自 Java,所以我的想法可能与 RoR 开发人员的方式不同。 :-)

我需要做的是创建一些数据访问层,假设它将是访问用户,所以就这样吧 UserDAO.rb 基本上将使用 ActiveRecord直接访问数据库访问一些键值存储或 我能想到的其他任何东西。

从技术上讲,由于我们在 Ruby 中没有接口,我可以让 UserDAO.rb “拥有”实现(基本上,我说的是组合),这可能是我们需要的任何东西,例如 UserDAOActiveRecord.rb 或 UserDAOMongo.rb 或其他类似的事情。 UserDAO.rb 基本上将调用实现的方法,仅此而已。应该很容易在实现之间切换。

虽然这听起来确实是一个可能的解决方案,但我期待听到 Ruby 世界中解决此问题的最佳实践。谢谢!

So, I have Ruby on Rails application. Blank for now. And let me say right from the beginning that most of my experience is from Java, so I might be thinking not the way RoR devs do. :-)

What I need to do is to create some Data Access Layer, say it will be access users, so let it be
UserDAO.rb which will be basically then using ActiveRecord or directly accessing the database or accessing or some key-value storage or anything else I can think of.

Technically, as we don't have interfaces in Ruby, I can make UserDAO.rb to "have" the implementation (basically, I am talking about composition), which may be anything we need, say UserDAOActiveRecord.rb or UserDAOMongo.rb or anything else like that. UserDAO.rb will basically call the methods of the implementation and that's it. Should be easy to switch between implementations.

While it does sound like a possible solution, I am looking forward to hear what are the best practices for this problem in the Ruby world. Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

羁客 2024-10-25 02:30:02

您必须寻找除 ActiveRecord 之外的 Ruby 类(正如所指出的,它是一个对象关系映射器,因此没有单独的数据访问层)。

您可能想查看: https://github.com/jeremyevans/sequel

您可以创建一个类 Person,其中包含使用 Sequel 实例与数据库对话的方法。

这段未经测试的代码说明了为什么这可能不是一个好主意:

class Person
  attr_reader :first_name, :last_name

  DataSource = Sequel.sqlite('my_app.db')[:people]

  def initialize(record)
    @first_name = record.first_name
    @last_name = record.last_name
  end

  # Find a record from the database and use it to initialize a new Person object 
  def self.find_by_id(id)
    self.new(Table.where(:id => id))
  end
end

You will have to look for a Ruby Class other than ActiveRecord (which as pointed out is an Object Relational Mapper, so has no separate data access layer).

You might want to look at: https://github.com/jeremyevans/sequel

You could create a class, Person, which contains methods which use an instance of Sequel to talk to the database.

This untested code demonstrates why this might not be a great idea:

class Person
  attr_reader :first_name, :last_name

  DataSource = Sequel.sqlite('my_app.db')[:people]

  def initialize(record)
    @first_name = record.first_name
    @last_name = record.last_name
  end

  # Find a record from the database and use it to initialize a new Person object 
  def self.find_by_id(id)
    self.new(Table.where(:id => id))
  end
end
季末如歌 2024-10-25 02:30:02

请记住,ActiveRecord 不仅是访问数据库的一种方式,它还是将数据集成到应用程序中的一种模式:每个模型控制自己的数据并根据需要使用模型存储/检索/查询它的想法代表数据库行的实例。

当然,您不必使用该模式,但它是 Rails 的核心之一,因此通过将 ActiveRecord 视为另一种要抽象的数据访问方法,您将失去很多功能。

另请注意,ActiveRecord 已经通过使用数据库适配器抽象出数据库类型,因此很容易放入 MySQL、Oracle 等。但它确实假定是关系数据库。

但是,为了回答您的问题,实际上没有必要将数据访问实现包装在另一个类中以确保接口的一致性。正如你所说,Ruby 没有 Java 类型的接口,但 Ruby 世界通常也不会试图确保开发人员只能做合法的事情。您可以创建一堆提供相同方法集的数据访问类,创建单元测试以确保这些方法是一致的(并充当这些方法的可执行文档),然后信任开发人员对任何方法进行正确的调用他们选择的实施。这与 Java 世界有很大的文化差异,在 Java 世界中,一切都被编码为接口,方法是最终的,对象是不可变的。这需要一些时间来适应。

Remember that ActiveRecord isn't only a way to access a database, it's also a pattern for how your data is integrated into your application: the idea that each model controls its own data and stores/retrieves/queries it as needed, with a model instance representing a database row.

Naturally, you don't have to use that pattern, but it's one of the cores of Rails, so by treating ActiveRecord as just another data access method to be abstracted, you're losing a lot of functionality.

Note also that ActiveRecord already abstracts out the database type by using a database adapter, so it's easy to drop in MySQL, Oracle, etc. But it does assume a relational database.

However, to answer your question, it's not really necessary to wrap your data access implementation in another class just to ensure a consistent interface. As you say, ruby doesn't have Java-type interfaces, but the ruby world also doesn't generally try to ensure that developers can only do legal things. You can create a bunch of data access classes that offer the same set of methods, create unit tests to ensure that those methods are consistent (and to act as executable documentation of those methods), and then trust developers to make the correct calls against whichever implementation they pick. It's a big cultural difference from the Java world, where everything is coded to interfaces and methods are final and objects are immutable. It takes some getting used to.

说好的呢 2024-10-25 02:30:02

Alex,我强烈建议您阅读《Agile Web Devoplment With Rails》(第 4 版)一书。 Active Record 实现了 ... Active Record 模式,因此 Class 就是 DAO(类方法代表 dao),而实例方法代表对象。

举个例子,

person = Person.find(3)   //Person is the dao
person.name = 'mick'      //name = is the setter for he instance
person.save               // well.. saves the object

我已经用 Java 编码了 10 年,然后才开始使用 ruby​​……这是一个很大的变化。

Alex, I strongly suggest you to get the book Agile Web Devoplment With Rails (4th edition). Active Record implements the ... active record pattern, so the Class is the DAO (the class methods represent the dao), while the instance methods represents the object.

So for example you can have

person = Person.find(3)   //Person is the dao
person.name = 'mick'      //name = is the setter for he instance
person.save               // well.. saves the object

I've coded in Java for 10 years and just started with ruby..... and it's quite a change.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文