抽象数据库和适当的控制器实现

时间:2012-06-11 23:32:25

标签: ruby-on-rails ruby architecture abstraction

我正在使用MongoDB作为我的项目的后端,但我并不特别希望在项目的生命周期中依赖Mongo,以防我后来决定更改它,或者在没有数据库的情况下单元测试更容易。但是,如上所述,我的控制器严格依赖于MongoDB。

主要取自MongoDB tutorial,我在config/initializers/mongo.rb文件中有以下内容。

MongoMapper.connection = Mongo::Connection.new('localhost')
MongoMapper.database = 'database'

if defined?(PhusionPassenger)
   PhusionPassenger.on_event(:starting_worker_process) do |forked|
     MongoMapper.connection.connect if forked
   end
end

在查询美国各州的控制器中,我有以下代码:

class StateController < ApplicationController
    def index
        states = MongoMapper.connection.db('database').collection('state').find()

        render :json => states
    end
end

我看到了一些问题(可能还有更多):

  1. 如前所述,控制器对MongoDB有很强的依赖性。
  2. 我没有使用MongoMapper类的database属性(它在控制器中是硬编码的)。
  3. 我不一定希望每次想要引用状态集时都通过HTTP端点 - 虽然我想保留此选项。例如,如果注册页面有一个下拉列表供用户选择其主页状态,那么要求客户端jQuery.get()填充状态列表似乎是愚蠢的。在我看来,让状态预先获取服务器端并在服务器上构建下拉列表会更有意义。
  4. 对于#3,我当然可以在任何动作方法中查询状态,这些动作方法呈现需要状态列表的视图并将它们保存在@states(或类似的东西)中,但这将是很多重复的代码。 / p>

    最好的方法是构建它以减少耦合和更多的代码重用?

1 个答案:

答案 0 :(得分:1)

首先,你应该有一个状态模型:

class State
  include MongoMapper::Document
end

然后,在您的控制器中,您应该通过以下方式访问:

class StatesController < ApplicationController
  def index
    render :json => State.all
  end
end

这样,你的控制器就不知道它正在使用什么底层数据存储。

最后,为了减少进行HTTP调用的需要,但假设您在javascript中构建它,则代码:

<div id="#states" data-states="<%= @states.to_json %>"></div>

然后从$("#states").data("states")

加载