如何在Rails 3中制作自定义助手?

时间:2012-05-11 00:34:24

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

我对Rails相当新,我对如何在if ... else语句之外传递局部变量感到困惑。看起来在辅助文件中创建方法是传统的方法,但我不知道如何做到这一点。

所以我想找一个使命的作者。如果任务的作者不存在,我想使用其父级教学大纲的作者(任务属于教学大纲)。然后我想打印出该作者的用户名。当我只处理一个任务时,我能够做到这一点,例如:

//controller
@mission = Mission.first
if !@mission.author.blank?
  @author = @mission.author
else
  @author = @mission.syllabus.author
end

//view
<%= @author.username %> 

但是当我处理foreach循环时,我不确定如何做到这一点:

//controller
@mission = Mission.all

//view 
<% @mission.each do |mission| %>
..(where do I put the logic of finding author? I can't put it in my controller anymore and it won't pass the @author variable outside the if else statement if I put the logic here in the view)..
<%= @author.username %>
<% end %>

我徒劳的尝试是创造一个帮手:

def author_getter(mission_id)
  @mission = Mission.find(params[:mission_id])
  if !@mission.author.blank? 
    @author = @mission.author 
    return @author
  else
    @author = @mission.syllabus.author  
    return @author
  end 
end

并将以下内容放入循环

<%= author_getter(mission) %>

然而,这不起作用。在if ... else语句之外传递变量的最佳方法是什么?

2 个答案:

答案 0 :(得分:3)

你的助手方法有点困惑。帮助者不应该在params中徘徊,他们应该只是用他们被召唤的论据做事。您正在传递mission_id但未使用它,当参数名称指示的时候,您还要使用(显然)mission对象调用它,而不是要求使用ID。此外,您不需要在助手中搞乱实例变量,只需要普通的旧变量即可。

调整界面以询问Mission对象,然后使用该对象:

def author_of(mission)
  mission.author.present?? mission.author : mission.syllabus.author
end

或者,由于mission.author应该是nil或那里,您可以利用nil的错误:

def author_of(mission)
  mission.author || mission.syllabus.author
end

然后在你的再培训局:

<!-- Note that you should use the plural @missions for a collection, you'll have to fix your controller as well. -->
<% @missions.each do |mission| %>
    <%= author_of(mission).username %>
<% end %>

当然,一旦我们简化并纠正了你的助手,你可能会认为它太小而不值得打扰;如果是这样,那么你可以放弃助手并在ERB中完成所有工作:

<% @mission.each do |mission| %>
    <%= (mission.author || mission.syllabus.author).username %>
<% end %>

但是,我认为你在错误的地方有这个逻辑:这应该在Mission本身内部,这样一切(其他模型,JSON构建器,......)都可以利用它。所以,这样的方法是有道理的:

class Mission
  def real_author
    author || syllabus.author
  end
end

然后你可以在你的ERB中说出这个:

<% @missions.each do |mission| %>
    <%= mission.real_author.username %>
<% end %>

答案 1 :(得分:0)

除非我误解了您的问题,否则您可以在循环中执行此操作而不使用查找。

//view 
<% @mission.each do |mission| %>
   <%= mission.author.username %>
<% end %>

请记住,您正在遍历所有Mission对象。一旦你有了一个任务对象,你就可以像往常一样访问作者。