返回结果返回查看

时间:2012-08-20 14:49:01

标签: ruby-on-rails haml helper

我试图将我的所有逻辑都排除在视图之外,并提出了下面的代码,尽管我已经知道它不会返回实际的分数值,它只会返回,如果它是一个胜利,丢失或领带

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

1 个答案:

答案 0 :(得分: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上的方法)

然后,我将演示如何使用提供的逻辑在助手中使用新的计划,或者只是查询结果本身并将其用作翻译查找的关键字(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.