current_suser的default_scope

时间:2014-05-13 10:21:52

标签: ruby-on-rails devise

我正在尝试将gem devise实施到我的应用中。 在此之前,我的顶级模特是Album,但现在是belongs_to :user(来自设计)。

然后我添加到了albums_controller.rb:

before_action :authenticate_user!

效果很好 - 用户必须从现在开始登录。现在我希望他能够在他的范围内完成所有相册。我发现那种方法的存在:

def index
  @albums = Album.all
end

我可以使用:

@albums = current_user.albums

以及我所拥有的每种方法。我想知道是否有更好的方法 - 将current_user设置为相册控制器中每个操作/方法的默认范围。然后我找到了一些有趣的东西here。我可以将它添加到Album的模型中,但我不确定where的最佳costruct current_user子句。也许是这样的:

class Album < ActiveRecord::Base
  default_scope where(:user_id => current_user.id)
end

我甚至不确定这是否正确。我很感激你的意见。

4 个答案:

答案 0 :(得分:4)

您应该只使用常规命名范围:

scope :for_user, lambda{ |user| where(:user_id => user.id) }

然后在你的控制器中替换

带有@albums = Album.all

@albums = Album.for_user(current_user)

虽然理论上你可以将arguments传递给你的默认范围,但以上是首选方法。

答案 1 :(得分:4)

我不确定你为什么要这样做。最好的方法是使用控制器来确定模型的范围。这种类型的东西不属于该模型。

def index
  @albums = current_user.albums
end

如果要避免重复,请创建检索对象的方法。所以不要这样:

def show
  @album = current_user.albums.find(params[:id])
end
def edit
  @album = current_user.albums.find(params[:id])
end
# etc...

你可以这样做:

def index
  albums
end
def show
  album
end
def update
  if album.update(album_params)
end
# etc...

private
def albums
  @albums ||= current_user.albums
end
def album
  @album ||= current_user.albums.find(params[:id)
end

您甚至可以使用before_filter来避免从操作中调用相册方法,但这不是一个好方法。您总是倾向于忘记添加和删除过滤器中的操作。

before_action :set_album, only: [:show, :edit, :update, :destroy]
def set_album
  @album ||= current_user.albums.find(params[:id])
end

然后在一个地方创建实例变量。正如@wacaw建议的那样,如果这对您有吸引力,您可以进一步使用decent_exposure gem。就个人而言,我很高兴停在控制器上并在我的视图中使用实例方法。

如果您有更复杂的授权需求,我建议您使用punditcancan,尽管后者似乎没有得到积极维护。

Rails Casts上的decent_exposure还有更多内容。如果您真的喜欢这种类型的范围,请查看此Rails Cast on Multitenancy with Scopes。但这适用于拥有许多用户而非单个用户的组织。

答案 2 :(得分:1)

答案 3 :(得分:0)

您可以使用inherited_resources gem来保持控制器清除样板代码。以下代码是构建标准CRUD控制器所需的一切,该控制器自动范围为current_user并检查身份验证。

class AlbumsController < InheritedResources::Base
  before_action :authenticate_user!

  protected

  def begin_of_association_chain
    current_user
  end
end