【问题标题】:Nil errors in creating a hash in Ruby on Rails在 Ruby on Rails 中创建哈希时没有错误
【发布时间】:2015-06-14 04:07:47
【问题描述】:

在尝试创建此哈希 idea_benefit_count 时,我遇到了几个语法和 nil 问题。

@idea = @domain.ideas
@idea_evaluations = Array.new()
@idea.each do |idea|
  @idea_evaluations << idea.evaluations
end

@idea_benefit = []
if !@idea_evaluations.nil?
  @idea_evaluations.each do |eval|
    @idea_benefit << eval.benefit
  end
  @idea_benefit_count = Hash.new(0)
  @idea_benefit.flatten.each { |idea_benefit| @idea_benefit_count[idea_benefit] += 1 }
end

idea has_many domains,所以@idea 应该是具有给定@domain 的所有想法。

@idea_evaluationsbelong_to 特定 idea 的所有评估的数组。

@idea_benefit 是一个数组数组,其中包含每个评估的所有 benefit 条目。示例输出:[["happier_customers"], ["happier_employees"], ["happier_employees", "decreased_costs"], ["happier_employees"]]

idea_benefit_count 读取idea_benefit 并计算一个想法有多少每种类型的好处。 idea_benefit_count基于上述idea_benefit数组的输出为{"happier_customers"=&gt;1, "decreased_costs"=&gt;1, "happier_employees"=&gt;3}

(希望这个上下文涵盖所有内容)

我当前的错误是undefined method 'benefit' 在线@idea_benefit &lt;&lt; eval.benefitBenefitevaluation 的一个属性,所以它应该输出类似["happier_customers"] 的东西。

我意识到这段代码有点乱,所以任何建议都会对让整个事情正常工作非常有帮助。一个大问题是检查是否有属于ideaevaluations,因为如果它返回nil,则会引发错误。尝试使用 if !@idea_evaluations.nil? 检查解决该问题,但由于 undefined method 'benefit' 错误而无法对其进行测试。

编辑

@idea_evaluations = Array.new()
@idea.each do |idea|
  @idea_evaluations << idea.evaluations
end
@idea_evaluations.flatten!

@idea_benefit = []
unless !@idea_evaluations.nil?
  @idea_evaluations.each do |eval|
    @idea_benefit << eval.benefit
  end
  @idea_benefit_count = Hash.new(0)
  @idea_benefit.flatten.each { |idea_benefit| @idea_benefit_count[idea_benefit] += 1 }
end

【问题讨论】:

    标签: ruby-on-rails arrays ruby loops ruby-on-rails-4


    【解决方案1】:

    如果我理解您正在尝试做的事情,我看到的问题是您将idea.evaluations 转储到@idea_evaluations 的方式。
    @idea_evaluations 将是一组评估数组,而不是您想象的评估数组。
    例如[[eval1,eval2],[eval3,eval4,eval5]] 而不是 [eval1, eval2, eval3, eval4, eval5]

    当您尝试访问福利时,它会尝试为不存在的数组寻找福利方法。

    尝试修改

    @idea.each do |idea|
      @idea_evaluations << idea.evaluations
    end
    

    成为

    @idea.each do |idea|
      @idea_evaluations << idea.evaluations
    end
    @idea_evaluations.flatten!
    

    在 ruby​​ 中你通常不这样做

    if !condition 
    

    你通常会这样做

    unless condition
    

    【讨论】:

      【解决方案2】:

      使用map 构建数组(或使用 ActiveRecord 范围以提高效率)。

      @idea_evaluations = @domain.ideas.map(&:evaluations)
      
      # Remove nil values before moving on to the next chunk.
      @idea_evaluations.reject! { |i| i.nil? }
      @idea_benefits = @idea_evaluations.map(&:benefit)
      

      如果您使用范围方法,它看起来类似于以下内容:

      # in Benefit.rb 
      scope for_domain ->(domain_id){ joins(:evaluation => :idea).where(idea: {domain_id: domain_id}) }
      
      # called like this 
      @idea_benefits = Benefit.for_domain(@domain.id)
      

      inject 是一个有用的信息汇总工具。

      @idea_benefits .inject({}) do |eval, result|
        result[eval] += 1 
        result
      end
      

      【讨论】:

        【解决方案3】:

        我相信这整个 sn-p 可以替换为:

        @idea_benefit_count  = 
          @idea.flat_map(&:evaluations)
               .flat_map(&:benefit)
               .each_with_object(Hash.new{0}) {|k, h| h[k] += 1}
        

        【讨论】:

        • 这给了我SyntaxError: (irb):47: syntax error, unexpected '.' .each_with_object(Hash.new{0}) {|k, h| h[k] += 1} 如果可能的话,我想用它来使它更简洁,你知道为什么会抛出这个错误吗?
        • 这可能是几件事......你确定你是一次复制粘贴所有内容而不是逐行复制吗?
        • 是的,我一下子把它都放进去了?
        猜你喜欢
        • 2014-04-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-21
        • 2013-03-02
        • 2013-05-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多