将应用程序范围扩展到current_project的便捷方法

时间:2014-02-20 17:24:20

标签: ruby-on-rails ruby ruby-on-rails-4 routes

我有一个应用程序可以将所有内容置于Project下。所有视图都要求项目可用。这允许我使用current_project方法:

current_project = current_user.projects.find(params[:project_id)

虽然这很方便,但这意味着我的路由总是必须在项目范围内,我不能使用浅路由。当你有四个嵌套级别时,这可能会很糟糕。

resources :projects do
  resources :posts do
    resources :attachments
    resources :comments do
      resources :attachments
    end
  end
end

这种嵌套意味着复杂的路线和复杂的测试:

form_for [@project, @post, @comment, @attachment] ...

这也意味着很多重复,因为像attachments这样的多态模型必须适用于嵌套在不同级别的postscomments

form_for [@project, @attachable, @attachment] # ... for posts
form_for [@project, @post, @attachable, @attachment] # ... for comments

所以我转而使用浅路线。这是一种解脱,但这有另一个令人讨厌的副作用:

current_project不再容易实现。例如,要获得Attachment,我需要经历三个父母:

@attachment.comment.post.project

由于所有观点都需要它,我几乎每次都需要这样做。

@project = @post.project
@project = @comment.post.project
@project = @attachment.comment.post.project

是否有一些中间地带,我可以使用方便的current_project方法,而不必将我的路线嵌套4级?我也不想使用子域名。

3 个答案:

答案 0 :(得分:1)

再看一下,我认为最好将current_project_id保存到users表中,以便当有人切换项目时更新他们的记录。然后,你的current_project方法只是

#application.rb
def current_project
  @current_project ||= current_user.current_project
end

您需要添加

#user.rb
belongs_to :current_project, :class_name => "Project"

并且,在任何页面加载时,您总是知道您正在处理哪个项目,只需使用此方法查看users表。

答案 1 :(得分:0)

#in app/controllers/application.rb
def current_project
  unless @current_project
    @current_project = (@post && @post.project) || (@comment && @comment.post.project) || (@attachment && @attachment.comment.post.project)
  end
  @current_project
end

我在方法中使用实例变量@current_project,这样如果在单个动作/渲染中多次调用current_project,它只需要进行一次计算:随后它将只从@current_project中读出它。 / p>

答案 2 :(得分:0)

我建议添加一个before_action,将@current_project加载到每个控制器。