Rails 3: как писать области DRYer - PullRequest
1 голос
/ 11 мая 2011

Я пишу очень похожий код в двух местах: один раз для определения (виртуального) логического атрибута в модели и один раз для определения области поиска записей, соответствующих этому условию.По сути,

scope :something, where(some_complex_conditions)

def something?
  some_complex_conditions
end

Простой пример: я моделирую членство в клубе;Member платит Fee, который действителен только в определенном year.

class Member < ActiveRecord::Base
  has_many :payments
  has_many :fees, :through => :payments

  scope :current, joins(:fees).merge(Fee.current)

  def current?
    fees.current.exists?
  end
end

class Fee < ActiveRecord::Base
  has_many :payments
  has_many :members, :through => :payments

  scope :current, where(:year => Time.now.year)

  def current?
    year == Time.now.year
  end
end

Есть ли способ DRYer для написания областей, которые используют виртуальные атрибуты (или, альтернативночтобы определить, соответствует ли модель условиям области видимости)?

Я довольно новичок в Rails, поэтому, пожалуйста, укажите, что я делаю что-то глупое!

Ответы [ 3 ]

1 голос
/ 11 мая 2011

Это не ответ на вопрос, но в вашем коде есть ошибка (в случае, если вы используете нечто подобное в рабочей среде): Time.now.year вернет год, когда был запущен сервер. Вы хотите запустить эту область в лямбде, чтобы она работала так, как ожидалось.

scope :current, lambda { where(:year => Time.now.year) }
0 голосов
/ 11 мая 2011

Нет, нет лучшего способа сделать то, что вы пытаетесь сделать (кроме как принять к сведению комментарий Жеро). В своей области вы определяете фильтр уровня класса, который будет генерировать SQL, который будет использоваться для ограничения результатов, которые возвращают ваши искатели, в атрибуте, который вы определяете тест уровня экземпляра, который будет выполняться на конкретном экземпляре этого класса.

Да, код похож, но он выполняет разные функции в разных контекстах.

0 голосов
/ 11 мая 2011

Да, вы можете использовать один или несколько параметров с лямбдой в ваших областях. Предположим, что у вас есть набор предметов, и вы хотите вернуть те, которые являются «Boot» или «Helmet»:

  scope :item_type, lambda { |item_type|
    where("game_items.item_type = ?", item_type )
  } 

Теперь вы можете сделать game_item.item_type ('Boot'), чтобы получить только ботинки, или game_item.item_type ('Helmet'), чтобы получить только шлемы. То же самое относится и к вашему делу. Вы можете просто иметь параметр в своей области, чтобы проверить одно или несколько условий в одной и той же области в режиме DRYer.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...