代码之家  ›  专栏  ›  技术社区  ›  dav

在Rails中寻找不定期检查数据库的方法

  •  1
  • dav  · 技术社区  · 15 年前

    我有一个应用程序,在这个应用程序中,每当加载一个页面时,需要检查一个用户是否在等待另一个用户。我有这样的条目:

    def self.up
        create_table :calls do |t|
          t.string   "user1_id"
          t.string   "user2_id"
          t.boolean  "active", :default=>false
          t.string   "meeting_url"
          t.string "embed_url"
          t.timestamps
        end
    

    当前,应用程序检查calls表中是否有任何与用户ID匹配的调用,如果active==true。如果有结果,它们将显示给用户。问题是,这就需要为每次页面加载都调用db。所以我的问题是:

    1)这是最有效的方法吗?(显然我很怀疑) 2)如果是,如何以最干燥的方式完成这项工作?

    非常感谢

    戴夫

    2 回复  |  直到 15 年前
        1
  •  0
  •   jmaxyz    15 年前

    如果您的应用程序需要知道某个用户在每次页面加载时是否有一些调用等待,并且该信息只保存在数据库中,那么是的,我希望您在每次页面加载时都必须查询数据库中的该信息。

    就干燥而言,Rails在整个MVC堆栈中提供了许多机制,以确保保持干燥和可维护性:

    在模型中,可以向调用模型中添加一个类方法,以封装查询等待调用的逻辑。可能是这样的:

    class Call < ActiveRecord::Base
    
    def self.awaiting_for_user user
        self.all(:conditions => ['user_id = ? AND active = true', user])
    end
    

    通过将查询封装在这样的方法中,可以确保如果查询该信息的基础逻辑发生更改,则不会调用该方法。

    您可以在控制器/操作集上运行此代码,而不是将此方法调用添加到每个控制器操作(索引、显示等),而是使用控制器的“筛选前/筛选后/筛选后”方法。

    class ApplicationController
        before_filter :load_current_user
        before_filter :load_current_users_calls
    
    ....
    protected
    
        def load_current_user
            # You could encapsulate this method in your User model
            @user = User.find(session[:user_id])
        end
    
        def load_current_users_calls
             @calls = Call.awaiting_for_user(@user)
        end
    

    使用before_filter选项,如:except和:仅用于精确定位在特定控制器操作中使用的筛选器。此外,在applicationcontroller中声明实际的load_current用户调用方法时,确保每个子类控制器都有该方法,而不必在applicationcontroller中放置before_filter声明——您可以将它放在任何要运行before_筛选器的控制器中。

    在视图层中,您可以进行部分操作,以便在标准布局中轻松显示@calls。您可以在布局中添加类似的内容:

    <%- if @calls && !@calls.blank? -%>
    <%= render :partial => 'awaiting_calls_display', :locals => {:calls => @class} =%>
    <%- end -%>
    

    或者,如果这不适合您的布局,您可以从任何适用的视图调用它。

        2
  •  0
  •   SFEley    15 年前

    我觉得这个模型有点混乱。就是那个 用户标识 用户2ID 特别是,这让我有种不安的感觉——它告诉我,你并不真正关心谁在等谁,这两个用户之间没有区别,而且你很乐意在每次查找用户时都用“或”来检查两个列。这对Rails和SQL来说都是一团糟。

    这也不是你描述的商业问题。这两个用户之间的关系是 完全对称:一个人在等另一个人。很明显,你在乎的是哪一个,但你并没有为它建模。或者,如果你是的话,你给他们起的名字很差。

    我对您的申请没有确切的了解,但我可能会做两件事来清理:

    1. 将这些用户字段细化为非对称关系:可能是发起者和接收者。你可以给他们打电话 呼叫者ID 卡莱耶德 . 无论什么。然后每个会话只需检查 卡莱耶德 字段(我想)查看是否有人在等待那个用户。这也许足够了。如果是这样的话,就不要麻烦第二步了。

    2. 将“等待”关系推到一个单独的、更简单的模型中,该模型针对快速写入和删除进行了优化。当有人试图与其他人发起呼叫时,您将写入在收件人上键入的等待存储区。我可能会用 内存缓存 直接针对这个而不是数据库——那么您几乎没有延迟,频繁的读取和更新不会妨碍其他操作。(或者,根据您使用的数据库技术,这可能是调用基于内存的表的罕见情况之一。)

    在我看来你好像在想 数据优先 并尝试使您的代码适合您所拥有的表结构。这不是铁路的最佳选择。想想你的 行为 首先,让您的数据模型适应您希望用户能够做的事情。