Rails: dlaczego z exclusive scope jest chroniony? Jakieś dobre praktyki, jak z niego korzystać?

Podany model z default_scope do filtrowania wszystkich nieaktualnych wpisów:

# == Schema Information
#
#  id          :integer(4)      not null, primary key
#  user_id     :integer(4)      not null, primary key
#  end_date    :datetime        

class Ticket < ActiveRecord::Base
  belongs_to :user
  default_scope :conditions => "tickets.end_date > NOW()"
end
Teraz chcę dostaćdowolny bilet. W tym przypadku with_exclusive_scope jest droga, ale czy ta metoda jest chroniona? Tylko to działa:
 Ticket.send(:with_exclusive_scope) { find(:all) }
Niezły hack, co? Więc jaki jest właściwy sposób użycia? Szczególnie w przypadku asocjacji jest jeszcze gorzej (biorąc pod uwagę, że użytkownik ma wiele biletów): {]}
 Ticket.send(:with_exclusive_scope) { user.tickets.find(:all) }

That ' sso Brzydula!!! - nie może być rails-way!?

Author: John Topley, 2009-10-30

3 answers

Dla każdego, kto szuka sposobu Rails3, możesz użyć metody unscoped:

Ticket.unscoped.all
 164
Author: brad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-07 20:38:05

Unikać default_scope jeśli to możliwe . Myślę, że powinieneś ponownie zadać sobie pytanie, dlaczego potrzebujesz default_scope. Przeciwstawienie a default_scope jest często bardziej kłopotliwe niż jest warte i powinno być stosowane tylko w rzadkich przypadkach. Ponadto użycie default_scope nie jest zbyt odkrywcze, gdy połączenia biletów są dostępne poza Modelem biletu(np. " zadzwoniłem account.tickets. Dlaczego nie ma tam moich biletów?"). Jest to jeden z powodów, dla których with_exclusive_scope jest chroniony. Powinieneś skosztować octu syntaktycznego, gdy potrzebujesz użyj go.

Jako alternatywę, użyj gem / plugin jak pacecar , który automatycznie dodaje przydatne named_scopes do modeli dając Ci bardziej odkrywczy kod wszędzie. Na Przykład:

class Ticket < ActiveRecord::Base
  include Pacecar
  belongs_to :user
end

user.tickets.ends_at_in_future # returns all future tickets for the user
user.tickets                   # returns all tickets for the user

Możesz również ozdobić swój model użytkownika, aby powyższy kod był czystszy:

Class User < ActiveRecord::Base
  has_many :tickets

  def future_tickets
    tickets.ends_at_in_future
  end
end

user.future_tickets # returns all future tickets for the user
user.tickets        # returns all tickets for the user

Uwaga: rozważ również użycie bardziej idiomatycznej nazwy kolumny datetime, takiej jak ends_at zamiast end_date.

 33
Author: Ryan McGeary,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-30 13:05:03

Musisz zamknąć metodę protected wewnątrz metody modelowej, coś w stylu:

class Ticket < ActiveRecord::Base
  def self.all_tickets_from(user)
    with_exclusive_scope{user.tickets.find(:all)}
  end
end
 20
Author: Vlad Zloteanu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-30 10:25:43