0

我想保留通常会被销毁的旧记录。例如,用户加入了一个项目,但后来被踢出。我想保留 user_project 记录,其中包含将记录标记为非活动的内容。为此,我在每个模型中使用状态属性来定义每个记录的当前状态。

几乎我所有的“查询”都只需要“活动”记录,状态 == 1 的记录,我想使用 ActiveRecord 助手(find_by 等)。我不想添加到所有“find_by”中,我使用“_and_state”来仅查找活动的记录。

这就是我现在所拥有的:

u = UserProject.find_by_user_id_and_project_id id1, id2

这就是我对所有模型的每个这样的查询都会有的:

u = UserProject.find_by_user_id_and_project_id_and_state id1, id2, 1

实现这一点的最简洁的方法是什么(状态维护和更简洁的查询代码)?

4

3 回答 3

2

create a scope in your model UserProject:

class UserProject < ActiveRecord::Base
  scope :active, where(:state => 1)
end

and "filter" your queries:

u = UserProject.active.find_by_user_id_and_project_id id1, id2

if you "almost allways" query the active UserProjects only, you can define this scope as default_scope and use unscoped if you want to query all records:

class UserProject < ActiveRecord::Base
  default_scope where(:state => 1)
end

u = UserProject.find_by_user_id_and_project_id id1, id2  # only active UserProjects
u = UserProject.unscoped.find_by_user_id_and_project_id id1, id2 # all states
于 2013-06-27T13:50:32.923 回答
1

我试图将其添加到 Martin 的答案中,但必须审查我的编辑,因此即使 Martin 的答案很棒,我们也可以通过默认范围的想法对其进行一些改进。默认范围始终应用于您添加它们的模型上的查找器,除非您专门关闭默认范围:

class UserProject < ActiveRecord::Base
  default_scope where(:state => 1)
end

马丁给出的例子变成了:

u = UserProject.find_by_user_id_and_project_id id1, id2

在这种情况下,即使没有指定您想要 state == 1,您也只会获得活动记录。如果这几乎总是您想要的,那么使用默认范围将确保您不会意外地在代码中的某处遗漏“.active”,从而可能会产生难以发现的错误。

如果您像这样指定默认范围:

default_scope :conditions => {:state => 1}

那么新创建的 UserProjects 将已经将状态设置为 1,而无需您显式设置它。

以下是有关默认范围的更多信息:http: //apidock.com/rails/ActiveRecord/Base/default_scope/class

当您需要查找所有记录时,如何暂时关闭它们:http: //apidock.com/rails/ActiveRecord/Scoping/Default/ClassMethods/unscoped

于 2013-06-27T14:02:41.443 回答
1

以下是您可能想要选择的一系列软删除 gem ,它们提供了一个经过深思熟虑和调试的很好的抽象:

尽管如果这恰好是您的第一个 Rails 应用程序,我赞同 Martin 的建议,即滚动您自己的实现。

于 2013-06-27T14:06:34.320 回答