0

我试图将我所有的逻辑都排除在视图之外,并提出了以下代码,尽管我拥有的是它没有返回实际的分数值,它只是返回如果它是赢、输或平

def find_result(schedule)
return "not required" if schedule.event != '1' or schedule.time >= Time.now
if schedule.for.nil? or schedule.against.nil?
  "Not Entered"
else
  tie = '<b>T</b> '
  tie << schedule.for.to_i
  tie << ' - '
  tie << schedule.against.to_i
  win = '<b>W</b> '
  win << schedule.for.to_i
  win << ' - '
  win << schedule.against.to_i
  return raw tie  if schedule.for.to_i == schedule.against.to_i
  schedule.for.to_i > schedule.against.to_i ? (raw win) : "Lost"
end

结尾

4

1 回答 1

2

不要<<与整数一起使用。请参阅文档:
http ://www.ruby-doc.org/core-1.9.3/String.html#method-i-3C-3C

它可能会将您的赢/输数字转换为 HTML 中未显示的字符。

使用格式化程序或其他东西,或者可能只是to_s而不是to_i在附加数字时。

使用字符串格式的示例(未经测试):

def find_result(schedule)
  return "not required" if schedule.event != '1' or schedule.time >= Time.now
  if schedule.for.nil? or schedule.against.nil?
    "Not Entered"
  elsif schedule.for.to_i < schedule.against.to_i
    "Lost"
  else
    raw "<b>%s</b> %d - %d" % [
      schedule.for.to_i == schedule.against.to_i ? 'T' : 'W',
      schedule.against.to_i,
      schedule.for.to_i
    ]
  end

编辑:重构

将逻辑排除在视图之外是好的,但将其中的一些移到模型中会更合适,即时间表的结果(未进入、获胜、失败、平局)

在示例中,我将创建一个简单的内部类来封装该逻辑,Schedule 使用它来了解自己的结果。您可以通过多种方式执行此操作(例如,模块与类,或直接在 Schedule 上的方法)

然后,我将演示如何使用提供的逻辑在帮助程序中使用新计划,或者简单地查询结果本身并将其用作翻译查找 (I18n) 的键。

请注意,这是未经测试的并且有点伪代码(我没有特别使用任何 I18n 库,只是猜测方法和翻译格式)。但它应该进行一些调整,或者至少让您了解另一种做事方式。

class Schedule

  # The schedule jus instantiates a result object when you ask for one.
  # For convenience the result's to_s is it's value, e.g. "win"
  def result
    Result.new(self.for, self.against)
  end

  # delegate methods querying the result
  delegate :win?, :loss?, :tie?, :not_entered?, :to => :result

  class Result
    Values = %(win loss tie not_entered)
    Win = Values[0]
    Loss = Values[1]
    Tie = Values[2]
    NotEntered = Values[3]

    attr_reader :for, :against

    def initialize(_for, against)
      @for = _for
      @against = against
    end

    def value
      return NotEntered unless [@for, @against].all?
      case v = @for - @against
      when v.zero? then Tie
      when v > 0 then Win
      else Loss
      end
    end

    alias :to_s :value

    def not_entered?; self.value == NotEntered end
    def win?; self.value == Win end
    def loss?; self.value == Loss end
    def tie?; self.value == Tie end
  end
end

# then in your helper, something like
def find_result(schedule)
  # you'd want to refactor this requirement part too
  return "not required" if schedule.event != '1' or schedule.time >= Time.now

  # Now you could do it essentially the way you had, with ifs or a 
  # case statement or what have you, but the logic for the result is kept 
  # where it belongs, on the class.
  if schedule.not_entered?
    "Not Entered"
  elsif schedule.loss?
    "Loss"
  else
    prefix = schedule.win? ? "W" : "T"
    raw "<b>%s</b> %d - %d" % [prefix, schedule.for, schedule.against]
  end

  # OR you could use some kind of translation library using the `value` 
  # returned by the result.  Something like:
  key = ["schedule", schedule.outcome.value].join(".")
  raw I18n.translate(key, {:for => schedule.for, :against => schedule.against})
end

# if you used the latter, it would lookup the translation in some other place, 
# e.g. some config JSON, which might look like this (more or less, and 
# depending on the lib you use):

{
  "schedule": {
    "win": "<b>W</b> {{for}} - {{against}}",
    "tie": "<b>T</b> {{for}} - {{against}}",
    "loss": "Loss",
    "not_entered": "Not Entered"
  }
}

# The translation has a few advantages.  It would allow you to sub in other 
# languages, but also, it conveniently keeps all of the app's text in one 
# place, if you stick to using it.
于 2012-08-20T16:04:50.630 回答