从文档数组创建关联代理

时间:2012-09-26 14:00:50

标签: ruby-on-rails ruby authentication mongoid access-control

我有一个我的项目模型设置为这样的东西(使用Rails 3.2和Mongoid 3.0):

class Parent
  include Mongoid::Document

  has_many :kids

  def schools
    return kids.map { |kid| kid.school }
  end
end

class School
  include Mongoid::Document

  has_many :kids
end

class Kid
  include Mongoid::Document

  belongs_to :parent
  belongs_to :school
end

My Parent模型充当我使用Devise设置的标准用户模型。我希望SchoolController使用indexshow方法,只允许访问父母有孩子的学校。根据此网站,最好的方法是执行此操作:{{ 3}},就是这样做:

def index
  @schools = current_user.schools
end

def show
  @school = current_user.schools.find(params[:id])
end

但是,由于Mongoid不允许has_many :through关系,Parent#schools是一个自定义方法,它返回一个数组,而不是一个关联代理,因此#find不是一个方法可以使用。有没有办法从文档数组创建关联代理?或者有更聪明的方法来处理这个简单的访问控制问题吗?

1 个答案:

答案 0 :(得分:0)

到目前为止,我能够解决此问题的最优雅的方法是将自定义方法附加到Parents#schools返回的数组。

我给返回的数组一个#find方法:

class Parent
  include Mongoid::Document

  has_many :kids

  def schools
    schools = self.kids.map { |kid| kid.school }

    # Returns a school with the given id. If the school is not found, 
    # raises Mongoid::Errors::DocumentNotFound which mimics Criteria#find.
    def schools.find(id)
      self.each do |school|
        return school if school.id.to_s == id.to_s
      end
      raise Mongoid::Errors::DocumentNotFound.new(School, {:_id => id})
    end

    return schools
  end
end

这样我可以保持我的Controller逻辑简单和一致:

class ParentsController < ApplicationController

  def show
   @school = current_user.schools.find(params[:id])
  end

end

目前还不确定是否有更好的方法。