Tag: Rails

Ruby, Rails, moduły, mixin i scope

Dokonując refaktoryzacji, stanąłem przed pewnym problemem. Mianowicie miałem już stworzony interfejs który chciałem wydzielić także do innej klasy. Problemem było to że klasy te mają różnych rodziców i nie chciałem tworzyć dla nich wspólnego potomka (a Ruby nie umożliwia wielodziedziczenia). Z pomocą przychodzą wtedy moduły.

Funkcjonalnością jaką chciałem wydzielić, było zarządzanie e-mailami. O ile dołączanie metod instancyjnych i klasowych nie stanowi problemu, o tyle dołączenie scope'a już tak.

Aby dołączyć scope'a z ActiveRecord do mixinu, w taki sposób aby działał w modelu, musimy posłużyć się metodą lambda. Rozszerzamy metodę included naszego modułu w taki sposób:

def self.included( k )

# Konta których email nie został aktywowany w przeciagu 24h
k.scope :unactivated, lambda{where('email_change < ?', 24.hours.ago)}

end

Nie jest to może "mega" ładne, jednak działa :)

Rails 3.0.1 na 3.0.2 i I18n oraz problemy z modułami

Przechodząc z Rails 3.0.1 na 3.0.2 umknęła mi jedna rzecz. Nikt nigdzie nie wspomniał o tym, że zmianie ulega sposób budowania tłumaczeń dla I18n.

O ile zmiana na pola defaultowe, jest całkiem fajna (a i tak ją stosowałem dawniej, przy pomocy pewnego "hacka" ;) ), o tyle zmiany odnośnie klas w modułach, przyprawiły mnie o 25 minutowe wkurzenie.

Zanim jednak do tego przejdziemy, wspomnę o tej fajniejszej zmianie. Otóż dawniej, kiedy chcieliśmy przetłumaczyć nazwy atrybutów z różnych modeli, musieliśmy (stosowanie tricków się nie liczy) wypisywać wszystkie atrybuty dla wszystkich modeli. Kończyło się to sytuację gdzie np. pole "Imię" dla modeli User i Admin było tłumaczone tak:

activerecord:
    models:
      user: Użyszkodnik
      admin: Bóg
    attributes:
      user:
         name: Imię
      admin:
         name: Imię

było to trochę niewygodne. W nowym I18n, możemy zrobić to tak:

attributes:
   name: Imię

Oczywiście jeśli mamy model gdzie "name" to np. nazwa firmy, możemy wciąż dla tego wyjątku, dopisać całość w węźle Activerecord.

Druga zmiana też jest dobra, jednak trochę niespodziewana (a przynajmniej niezapowiedziana). Dawniej, polonizując modele w modułach, robiło się to tak(przykład dla klasy Profile::Admin):

activerecord:
    models:
      "profile/base": Profil
    attributes:
      "profile/admin":
        views: Ilość odwiedzin
        name: Imię
        surname: Nazwisko
        city: Miasto

jak widać powyżej, kiedy mieliśmy do czynienia z klasą w module, postępowaliśmy wg. schematu: moduł/model.

Nadeszło nowe i lepsze (ale cholerka, mogli powiadomić!). Od teraz moduł będzie stanowił gałąź-rodzica w pliku translacji, tak jak w poniższym przykładzie:

activerecord:
    models:
      profile:
         base: Profil
    attributes:
      profile:
         admin:
           views: Ilość odwiedzin
           name: Imię
           surname: Nazwisko
           city: Miasto

Takie zagnieżdżanie jest dużo wygodniejsze :)

Copyright © 2025 Closer to Code

Theme by Anders NorenUp ↑