【问题标题】:How to make custom Helpers in Rails 3?如何在 Rails 3 中制作自定义助手?
【发布时间】:2012-05-19 14:40:20
【问题描述】:

我对 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 语句之外传递变量的最佳方法是什么?

【问题讨论】:

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


    【解决方案1】:

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

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

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

    【讨论】:

    • 嗯,问题是有些任务没有作者,因为它是作为教学大纲的嵌套字段创建的。在那种情况下,它应该是mission.syllabus.username,所以我想要这个逻辑。
    • 这很令人困惑,但本质上用户可以自己创建任务,或者创建一个教学大纲并在其中包含许多嵌套任务。如果任务是单独创建的,“mission.author”会起作用并且是首选,但如果它是作为教学大纲创建的,则需要“mission.syllabus.author”。后来我做了它,即使它是作为一个教学大纲创建的,它也会将作者参数传递给任务作者,但是仍然有很多任务没有以前的作者
    【解决方案2】:

    您的辅助方法有点混乱。助手不应该在params 中闲逛,他们应该只是用他们被调用的参数来做事。您传入了 mission_id 但未使用它,当参数名称指示而不是要求 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
    

    然后在你的 ERB 中:

    <!-- 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 个问题:当我使用“mission.real_author”并且我想将其存储为“@author =mission.real_author”时,我应该在哪里定义 @author 变量?我是否必须在 .each do 循环中执行它,或者我可以在控制器中以某种方式定义它?
    • @KeithRyu:当你已经有@missions 时,你会想在迭代中使用&lt;% author = mission.real_author %&gt;,这样author 就不会泄露出去并在其他地方造成麻烦。
    • 我明白了 - 我想知道,因为我听说您不应该在视图中定义变量。对于模型、控制器和视图中通常应该包含的内容,我仍然有些困惑。有人告诉我,我应该在Model中写很多,控制器也应该很瘦,但是现在我的控制器最臃肿-这正常吗?
    • @KeithRyu:当您刚开始并且不确定自己在做什么时,这很正常。视图用于展示,视图中的变量通常只是其他东西的简写(例如author)。控制器将来自外部世界的数据路由到模型进行处理,然后将结果路由到视图进行呈现;它们应该又薄又紧。您的大部分逻辑应该以模型方法结束。如果您有一个胖控制器,那么您可能需要进行几次重构迭代才能将所有内容放在正确的位置,但只有经验(即犯错)会教您如何做。
    猜你喜欢
    • 1970-01-01
    • 2012-05-15
    • 2011-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-31
    • 1970-01-01
    相关资源
    最近更新 更多