все значения одного знака проверки - PullRequest
0 голосов
/ 23 сентября 2010

Пользователь должен вставить все значения как положительные, так и отрицательные.

Как мне установить такой же знак?

Правильно, я написал это на before_save ..

unless (self.alt_1 >= 0 && self.alt_2 >=0 && self.alt_3 >= 0 &&
      self.alt_4  >= 0 && self.alt_5 >= 0 && self.alt_6 >= 0) ||
    (self.alt_1 <= 0 && self.alt_2 <=0 && self.alt_3 <= 0 &&
      self.alt_4  <= 0 && self.alt_5 <= 0 && self.alt_6 <= 0)
  self.errors.add_to_base(_("All values sign should be same."))
end

Ответы [ 3 ]

3 голосов
/ 23 сентября 2010
first_sign = self.alt_1 <=> 0

(2..6).each do |n|
  unless (self.send("alt_#{n}") <=> 0) == first_sign
    errors.add_to_base(_("All values' signs should be same."))
    break
  end
end

С помощью этого метода мы сначала получаем знак alt_1, а затем видим, совпадают ли знаки остальных элементов (от alt_2 до alt_6). Как только мы находим тот, который не соответствует, мы добавляем ошибку проверки и останавливаемся. Он будет работать максимум 6 итераций и минимум 2.


Другой более умный, но менее эффективный метод - использовать удобный метод Enumerable#all?, который возвращает значение true, если переданный ему блок возвращает значение true для всех элементов:

range = 1..6

errors.add_to_base(_("All values' signs should be same.")) unless
  range.all? {|n| self.send("alt_#{n}") >= 0 } ||
  range.all? {|n| self.send("alt_#{n}") <= 0 }

Здесь мы сначала проверяем, все ли элементы больше 0, а затем, если все элементы меньше 0. Этот метод повторяет максимум 12 раз и минимум 6.

1 голос
/ 23 сентября 2010

Вот немного другой подход для вас:

irb(main):020:0> def all_same_sign?(ary)
irb(main):021:1>   ary.map { |x| x <=> 0 }.each_cons(2).all? { |x| x[0] == x[1] }
irb(main):022:1> end
=> nil
irb(main):023:0> all_same_sign? [1,2,3]
=> true
irb(main):024:0> all_same_sign? [1,2,0]
=> false
irb(main):025:0> all_same_sign? [-1, -5]
=> true

Мы используем оператор космического корабля , чтобы получить знак каждого числа, и мы гарантируем, что каждый элемент имеет тот же знак, что и элемент, следующий за ним. Вы также можете переписать его, чтобы сделать его более ленивым, выполнив

ary.each_cons(2).all? { |x| (x[0] <=> 0) == (x[1] <=> 0) }

но, на мой взгляд, это менее читабельно.

0 голосов
/ 23 сентября 2010
unless 
  [:<=, :>=].any? do |check|
    # Check either <= or >= for all values
    [self.alt1, self.alt2, self.alt3, self.alt4, self.alt5, self.alt6].all? do |v|
      v.send(check, 0)
    end
  end
  self.errors.add_to_base(_("All values sign should be same."))
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...