2013-04-14 29 views
1

我有一个使用以下模型设置的项目。每个->代表has_many关系:Ruby中嵌套路由的DRY控制器

Users->Goals->Milestones 

我的路线为Milestones这个样子的:

user_goal_milestones GET /users/:user_id/goals/:goal_id/milestones(.:format)   milestones#index 
         POST /users/:user_id/goals/:goal_id/milestones(.:format)   milestones#create 
new_user_goal_milestone GET /users/:user_id/goals/:goal_id/milestones/new(.:format)  milestones#new 
edit_user_goal_milestone GET /users/:user_id/goals/:goal_id/milestones/:id/edit(.:format) milestones#edit 
    user_goal_milestone GET /users/:user_id/goals/:goal_id/milestones/:id(.:format)  milestones#show 
         PUT /users/:user_id/goals/:goal_id/milestones/:id(.:format)  milestones#update 
         DELETE /users/:user_id/goals/:goal_id/milestones/:id(.:format)  milestones#destroy 

我发现自己在很多人的里程碑控制器做了很多这方面的“功能”:

def index do 
    @user = User.find(params[:user_id]) 
    @goal = Goal.find(params[:goal_id]) 
end 

def edit do 
    @user = User.find(params[:user_id]) 
    @goal = Goal.find(params[:goal_id]) 
end 

如何修改我的控制器,所以我不必须定义@user@goal所有的时间? 我试过把它们直接放在顶部,就在类定义块的开始之后,但它没有起作用。

回答

2

如果PARAMS都是一样的,你可以创建一个这样

def set_user_and_goal 
    @user = User.find(params[:user_id]) 
    @goal = Goal.find(params[:goal_id]) 

end 

的方法,并把它放在一个的before_filter顶部

before_filter :set_user_and_goal 

并将其设置为任何行动你喜欢

before_filter :set_user_and_goal, :only => [:edit, :index] 

编辑:

此外,以确保它不会在你的脸上吹起来,你可以做

@user = params.has_key?(:user_id) ? User.find(params[:user_id]) : nil 

和要求..通过执行类似

@goals = @user.goals.find(params[:goal_id]) 
确保目标属于用户
+0

甜!这真的很酷! – CamelBlues

+0

只是确保你总是有:user_id和:goal_id –

+0

这可能会导致应用程序出现意外的行为。您应该测试传递的目标是否真的属于传递的用户,否则事情会变得很糟糕。请在答案中添加测试。 – fotanus

1

您可以随时定义自己的helper方法

def goal_milestone(goal) 
    user_goal_milestone(goal.user, goal) 
end 

你可以把它添加到您的application_helper,然后使用任何在您的任何意见。这会在你的问题中提出小帮助方法。

寻找这样做的宝石没有给我看任何东西,但你可以用通用的方式编码。

+0

我会把这个帮手放在哪里?我将如何使用它? – CamelBlues

+0

更新了我的回答,你可能要检查 – fotanus