Ruby on Rails'除非'不工作

时间:2014-03-28 09:10:53

标签: ruby-on-rails ruby

这是一个关于Ruby on Rails的帮助呼吁,以阻止我的血压达到危险水平......

Ruby版本:ruby 2.1.0p0(2013-12-25修订版44422)

Rails版本:Rails 4.0.3

基本上我是在创建一个网络应用程序,可以让您获得有关设计的反馈,但我遇到的问题是“除非'关于在测试中显示标题的声明#index page

控制器(这适用于检索正确的测试):

def index

    # Gets all tests that have an end date before now
    @completed_tests = Test.where(["end_date < ?", DateTime.now]).order("end_date asc")

    # Gets all tests that have an end date after now        
    @current_tests = Test.where(["end_date > ?", DateTime.now]).order("end_date asc")

end

查看(测试#index)(这是导致我出问题的部分)

# This should be if there are no tests for the user, display the Blank state text
<% unless @completed_tests.nil? || @current_tests.nil? %>

        # If there are no completed tests this should not be displayed
        <% unless @completed_tests.nil? %>
            <h3>Completed Tests Section Header</h3>
        <% end %>


        <% @completed_tests.each do |test| %>
            # Do stuff (this works fine)
        <% end %>

        # If there are no current tests this should not be displayed    
        <% unless @current_tests.nil? %>
            <h3>Current Tests Section Header</h3>
        <% end %>

        <% @current_tests.each do |test| %>
            # Do stuff (this works fine)
        <%end%>

<% else %>

# This should be displayed if there are no completed or current tests
<p>Blank state text</p>

<% end %>

在没有测试时显示标题的问题,例如完成的测试标题显示在没有完成测试的情况下,如果没有测试,则同样如果我没有获得完成的和当前的测试标题而不是看到空白状态文本。

我尝试过的其他事情:

<% if @current_tests.nil? %>
    <h3>Completed Tests Section Header</h3>
<% end %>

上图:无论是否有测试

,都会删除标题
<% if @current_tests %>
    <h3>Completed Tests Section Header</h3>
<% end %>

上图:无论是否有测试(与上面的原始代码相同)都显示

非常感谢任何帮助......

4 个答案:

答案 0 :(得分:6)

您可以在Rails中使用obj.nil?,而不是使用obj.blank?,而Rails也会处理[]。在您的情况下,我认为您的查询可能会返回[]

<% unless @completed_tests.blank? %>
  <h3>Completed Tests Section Header</h3>
<% end %>

顺便说一句,我讨厌unless。我必须考虑一下它究竟意味着什么。对我而言,理解起来比if not要难得多。

对于后面的部分,

# This should be displayed if there are no completed or current tests
<p>Blank state text</p>

您需要(无计算测试)或(无当前测试)

<% if @completed_tests.blank? || @current_tests.blank? %>
  <p>Blank state text</p>
<% end %>

或(没有计算测试)和(没有计算测试)

<% if @completed_tests.blank? && @current_tests.blank? %>
  <p>Blank state text</p>
<% end %>

我不确定你的确需要什么,因为你的描述含糊不清。

答案 1 :(得分:3)

我+ 1&#39; d Arie Shaw的回答,但正如我写的那样,我觉得我只是发布了我的想法:

您使用.nil?可能是问题(来自另一个SO帖子) -

  

.nil?可用于任何对象,如果对象为零,则为true。

     

.empty?可用于字符串,数组和散列,并在以下情况下返回true:

     

字符串长度== 0数组长度== 0哈希长度== 0运行.empty?   在nil的东西上会抛出一个NoMethodError。

如Arie所述,.nil returns true if your variable is not set(如果它不在记忆中)。我会说,因为你设置了@completed_tests变量(并且它会返回一个结果......可能是空白的),你的.nil?方法将始终返回false,从而使你的逻辑不连贯:

  

在Ruby中,每个值都是一个对象。所以,零也是一个对象。事实上,   它是NilClass的一个实例:

我会说你最好使用Arie的blank?答案,或there is also .empty?

<% unless @completed_tests.empty? || @current_tests.empty? %>

<强>更新

这是我要做的。帮助程序未经测试,因此可能需要修复(特别是instance_variable_get方法):

#app/helpers/application_helper.rb
def tests(test)
  title = test.to_s.titleize
  content = "<h3>#{title} Tests Section Header</h3>"
  instance_variable_get(test).each do |test|
      content + "more html"
  end
  return content
end

<% case true %>
<% when @completed_tests.any? %>
  <%= tests(:completed) %>
<% when @completed_tests.any? %>
  <%= tests(:current) %>
<% else %>
  <p>Blank State Text</p>
<% end %>

答案 2 :(得分:1)

我会在这里改变一些事情,以使逻辑更容易,并可能在将来防止出现问题:

首先,确定测试的逻辑属于模型。所以以下控制器代码:

# Gets all tests that have an end date before now
@completed_tests = Test.where(["end_date < ?", DateTime.now]).order("end_date asc")

# Gets all tests that have an end date after now        
@current_tests = Test.where(["end_date > ?", DateTime.now]).order("end_date asc")

应该是

#test.rb

def completed
  self.end_date.to_i < Time.now.to_i 
end

def current
  self.end_date.to_i > Time.now.to_i
end

#test_controller.rb

def index
  @tests = Test.all
  @completed_tests = @tests.map(&:completed)
  @current_tests = @tests.map(&:current)
end

正如Arie Shaw所说,unless可能很难缠绕 - 特别是当你使用复杂条件时。所以我会改变这一行:

<% unless @completed_tests.nil? || @current_tests.nil? %>

分成部分的组成部分。类似的东西:

<% if @completed_tests.any? %> #any is the opposite equivalent of `blank` as in Arie Shaw's answer
  <%= render 'completed_tests' %>
<% end %>

<% if @current_tests.any? %> 
  <%= render 'current_tests' %>
<% end %>

<% if @current_tests.empty? && @completed_tests.empty? %>
   <p>Blank state text</p>
<% end %>

#_completed_tests.html.erb

<h3>Completed Tests Section Header</h3>

<% @completed_tests.each do |test| %>
  # Do stuff (this works fine)
<% end %>

#_current_tests.html.erb

<h3>Current Tests Section Header</h3>

<% @current_tests.each do |test| %>
  # Do stuff (this works fine)
<%end%>

通过这种方式,您可以一次提出一个问题,让您更容易跟踪。

答案 3 :(得分:0)

@completed_tests返回一个空数组,现在是ruby,如果你执行[].nil?,那么它将返回false,而使用blank?代替它,它在rails中定义,{ {1}}返回[].blank?。她是我在rails控制台中测试的内容

true

1代表Arie的回答