Rails:动态:finder_sql可能吗?

时间:2011-06-28 18:53:52

标签: ruby-on-rails ruby-on-rails-3

我的架构看起来像这样(简化):我的用户拥有不同的权限,可以创建经历某个生命周期的帖子(创建,审核,关闭,类似的东西......)。

以rails语言说class User has_many :posts,但我希望用户根据自己的权限查看帖子。如果用户享有特权,他应该能够看到所有帖子,如果不是,我希望他只看到已经审核过的帖子以及他自己的所有帖子。

现在,Post模型有一个类方法for_user(user),它只检查用户权限并返回相应的帖子。我理解,这不是Rails的方式,而是我想知道是否可以这样做:

class User
  has_many :posts, :finder_sql => finder
  #[...]
  def finder
    if self.has_privileges? #simplified...
      all
    else
      where( '[...]' )
    end
  end

不幸的是,这不起作用,因为rails期望:finder_sql只是一个字符串和一个字符串。有没有其他方法可以创建所需的行为?

3 个答案:

答案 0 :(得分:1)

我在当前的应用程序中做了类似的事情,我发现使用CanCan makes it very easy

当然,将您的权限逻辑转移到CanCan可能需要更多的努力,但它确实增加了很多灵活性。如果不出意外,您可以查看源代码以了解他是如何做到的。

答案 1 :(得分:0)

一种可能的方法是创建一个别名方法“all_posts”,然后定义自己的使用它的帖子方法:

class User
    has_many :all_posts, :class_name => "Post"

    def posts
       self.has_priviledges? ? self.all_posts : self.all_posts.where(...)
    end
end

这样做的缺点是失去了ActiveRecord为你做的一些缓存。例如,如果你两次调用user.all_posts,那么只有第一个调用sql,但是如果使用了where子句,则调用user.posts两次可能会两次调用sql。

答案 2 :(得分:0)

不是使用has_many关联(它添加了一堆setter方法,以及getter),而是简单地定义一个方法(你或多或少已经完成了):

def User < ActiveRecord::Base

   has_many :posts # written by the user

   # Posts the user can see
   def posts_visible_to
     if has_privileges?
        Post.all
     else
        posts
     end
   end

end

PS你错误拼写'特权'...... :)