开发者

Best practice to isolate data access layer in Ruby/Rails

开发者 https://www.devze.com 2023-02-11 03:10 出处:网络
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. :-)

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 c开发者_C百科an 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!


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


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消