Czyszczenie modelu

Klasa JournalEntry ma atrybut category - do wyboru z dość sporej liczby wartości oraz opis - wyznaczany na podstawie kategorii i ew. innych parametrów.

class JournalEntry
  serialize :options

  # Categories
  CATEGORY1 = 'CATEGORY1'
  CATEGORY2 = 'CATEGORY2'
  # ...
  CATEGORY100 = 'CATEGORY100'

  SUMMARIES = {
    CATEGORY1   => lambda { |o| 'Opis' },
    CATEGORY2   => lambda { |o| "Opis z parametrem #{o[:x]}" },
    # ...
    CATEGORY100 => lambda { |o| "#{o[:a]} + #{o[:b]} = #{o[:c]}" }
  }

  def summary
    SUMMARIES[category].call(options)
  end
end

j = JournalEntry.new(:category => JournalEntry::CATEGORY2, :options = { :x => "Bum" })
p j.summary

Da się coś zrobić z tym potworkiem? :slight_smile: Na STI trochę tych kategorii za dużo… Może wrzucić kategorie i lambdy do tabelki-słownika? (jako odrębny model?)

A czemu nie

[code]class JournalEntry
serialize :options

Categories

SUMMARIES = {
“1” => lambda { |o| ‘Opis’ },
“2” => lambda { |o| “Opis z parametrem #{o[:x]}” },

“100” => lambda { |o| “#{o[:a]} + #{o[:b]} = #{o[:c]}” }
}

def summary
SUMMARIES[category].call(options)
end
end

j = JournalEntry.new(:category => “2”, :options = { :x => “Bum” })
p j.summary[/code]
Ewentualnie::

def summary case category when 1 then 'opis' when 2 then "Opis z opcjami #{options[:x]}" end
normalnei nie zalecałbym takiego rozwiązania ze względu na to że nie można wtedy używać dziedziczenia, albo nadpisać części metod. Ale jeżeli metody wyglądają naprawdę w ten sposób to może to być opcja.

Albo elegancki DSLek

[code]class JurnalEntry
SUMMARIES = []
def self.g(&block) SUMMARIES << block end

g{ ‘Opis’ }
g{|o| “Opis z parametrem #{o}”}
… I tak 100 więcej …

def summary
SUMMARIES[category.to_i].call(options)
end[/code]
Oszczędzasz niewiele kodu, ale nie musisz się pieprzyć z liczeniem kategorii.

Może przenieś opisy do locali

pl: category_description: category1: "Opis ze zmienną %{x}" category2: "Opis ze zmienną %{x} i %{z}"

[code=ruby]class JournalEntry
def self.description(n, options={})
I18n.t(“category_description.category#{n}”, options)
end
end

j1 = JournalEntry.description(1, x: :foo)#=> “Opis ze zmienną foo”
j2 = JournalEntry.description(2, x: :foo, z: :bar) #=> “Opis ze zmienną foo i bar”[/code]
Edit: dżizas… późno już… 3-ci raz poprawiam ten kod :smiley:

Okej. Rozwiązanie z localami bije wszystkie moje. O ile nie ma innych wymagań to ja bym wybrał rozwiązanie Krzystofa. Jest niesamowicie eleganckie i pozwala definiować kolejne opisy niezależnie od kodu.

Dzięki za pomoc :slight_smile: