Как вывести вычисленное значение, используя .detect в Ruby on Rails?(или альтернатива .detect) - PullRequest
1 голос
/ 21 августа 2010

У меня сейчас есть следующий код:

events.detect do |event|

#detect does the block until the statement goes false

  self.event_status(event) == "no status"

end

То, что это делает, это выводит экземпляр события (где события - это строки разных моделей, которые все вместе вызывают события), когда метод event_status выводит «нет статуса».

Я хотел бы, чтобы вывод также включал значение для задержки, где:

delay = delay + contact.event_delay(event)

Метод event_delay не был написан, но он будет похож (возможно, излишним, но об этом я расскажу позже) на event_status при просмотре задержки между тем, когда событие было сделано и когда оно должно было быть сделано.

Вот как выглядит event_status для справки:

  def event_status target
  # check Ticket #78 for source

    target_class= target.class.name
    target_id   = target_class.foreign_key.to_sym

    assoc_name  = "contact_#{target_class.tableize}"

    r = send(assoc_name).send("find_by_#{target_id}", target.id) 
    return "no status" unless r
    "sent (#{r.date_sent.to_s(:long)})" 
  end

Моя концепция вывода должна быть [событие, задержка], чтобы, например, я мог получить доступ к нему как Array [: event] или Array [: delay], чтобы получить значение.

**** Я подумал, что, возможно, мне следует использовать yield для метода, но я не совсем собрал части (если блок, переданный методу, будет, например, с задержкой = +, я думаю, что это так). **

Я не женат на методе .detect, это то, с чего я начал, и, похоже, он работает, но он не позволяет мне вести подсчет рядом с ним.

1 Ответ

0 голосов
/ 21 августа 2010

Не совсем понятно, о чем вы просите, но звучит так, будто вы пытаетесь добавить задержку, пока не достигнете определенного условия, и вернуть запись, которая одновременно вызвала условие.

Вы можете подойти к этому, используя Enumerable#detect, как у вас, но сохранив счет:

def next_event_info
  next_event = nil
  delay = 0

  events.detect do |event|
    case (self.event_status(event))
    when "no status"
      true
    else
      delay += contact.event_delay(event)
      false
    end
  end

  [ next_event, delay ]
end

Обновите , если хотите сложить все задержки длявсе события, но также найти первое событие со статусом "no status":

def next_event_info
  next_event = nil
  delay = 0.0

  events.each do |event|
    case (self.event_status(event))
    when "no status"
      # Only assign to next_event if it has not been previously
      # assigned in this method call.
      next_event ||= event
    end

    # Tally up the delays for all events, converting to floating
    # point to ensure they're not native DB number types.
    delay += contact.event_delay(event).to_f
  end

  {
    :event => next_event,
    :delay => delay
  }
end

Это даст вам Hash взамен, что вы можете запросить как info[:event] или info[:delay].Имейте в виду, чтобы не злоупотреблять этим методом, например:

# Each of these makes a method call, which is somewhat expensive
next_event = next_event_info[:event]
delay_to_event = next_event_info[:delay]

Это сделает два вызова этого метода, каждый из которых будет перебирать все записи и выполнять вычисления.Если вам нужно использовать его таким образом, вы можете также сделать специальную функцию для каждой операции или кэшировать результат в переменной и использовать это:

# Make the method call once, save the results
event_info = next_event_info

# Use these results as required
next_event = event_info[:event]
delay_to_event = event_info[:delay]
...