Quick tip #2: Memoizable 2

Posted by wijet
on Wednesday, April 22

Gdy jakaś metoda wykonuje kosztowne obliczenia, a jej wyniku używamy wielokrotnie, rozsądnym jest obliczenia wykonać raz, a wynik zapamietać, tzw. cachowanie za pomoca zmiennych instancji. W takim wypadku, najczęsciej używamy idiomu "||="

class Bar
  def foo
    @foo ||= lambda {
      # jakies kosztowne obliczenia
      ...
    }.call
  end
end

Od railsów 2.2 możemy korzystać z metody :memoize, należy dodać metody z modułu ActiveSupport::Memoizable jako metody klasy.

class Bar
  extend ActiveSupport::Memoizable

  def foo
    # jakies kosztowne obliczenia
    ...
  end

  memoize :foo
end

Spowoduje to że za pierwszym wywołaniem metody :foo, metoda ta faktycznie zostanie wywołana, a wartość przez nią zwrócona zapamiętana (dziala to tak jak cachowanie w zmiennej instancji, czyli tylko w obrebie danego obiektu).

Każde następne wywołanie metody :foo, na tym konkretnym obiekcie, spowoduje zwrócenie zapamiętanej wartośći.

Jeśli chcemy wymusić wywołanie metody (tzn. bez cachu), jako ostatni parametr należy podać wartość true.

Linki

Module ActiveSupport::Memoizable

Memo-what? - A Guide to Memoization

Railscasts: Memoization

What's New in Edge Rails: Easy Memoization

Quick tip #1: tap i returning 3

Posted by wijet
on Saturday, April 11

Tym postem chcę rozpocząć serię którkich wpisów, o konkretnych metodach/konstrukcjach dostępnych w railsach, lub w samym Ruby, Za pomocą których możemy zrobić coś krócej, ładniej, bardziej ruby way.

Czasami pojawia się potrzeba wykonania na obiekcie pewnych operacji, a następnie zwrócenie go.

def foo(name)
  product = Product.find_or_initialize_by_name(name)
  # tu cos mieszamy z produktem
  ...
  # zapisujemy
  product.save
  product
end

jak widać na końcu musi być 'product' aby metoda zwracała product, inaczej :foo zwrociła by nam prawde lub fałsz, czyli wynik product.save

Możemy to bardzo elegancko, zastapić, poniższa konstrukcją

returning

def foo(name)
  returning Product.find_or_initialize_by_name(name) do |product|
    # tu cos mieszamy z produktem
    ...
    # zapisujemy
    product.save
  end
end

:returning przyjmuje obiekt, przekazuje go do bloku który otrzymuje, a następnie zwraca ten obiekt

tap

Za pomocą :tap możemy zrobić to samo, w troche inny sposob:

def foo(name)
  Product.find_or_initialize_by_name(name).tap do |product|
    # tu cos mieszamy z produktem
    ...
    # zapisujemy
    product.save
  end
end

Metoda :tap przyjmuje blok do którego przekazuje self (obiekt na którym została wywołana), a następnie po wykonaniu bloku zwraca self.

Obydwie metody sa dostepne w railsach. Warto wiedzieć że metoda :tap została włączona do Ruby w wersji 1.9.

Za pomocą metody :tap mozemy nawet wiecej poczarować, polecam przejrzenie poniższych linków:

Linki

Eavesdropping on Expressions

Tapping method chains with Ruby 1.9

Rails ActiveSupport returning Method

Mining ActiveSupport: Object#returning

Własne gemy - jak instalować gemy bez łaski root’a 0

Posted by wijet
on Wednesday, June 27

Najlepszym sposobem używania bibliotek ruby są gemy, bardzo prosta instalacja aktualizacja, rubygems także rozwiązuje problem zależności miedzy bibliotekami. Standardowo tylko administrator może dokonywać operacji na gemach. Możemy tak skonfigurować rubygems by korzystać z tych zainstalowanych już w systemie, a także instalować własne.

Tworzymy katalog dla gemów, następnie sprawdzamy gdzie w systemie są instalowane gemy domyślnie.

gem environment

Spisujemy ścieżki pod GEM PATH. Tworzymy w katalogu domowym plik .gemrc do którego pakujemy te ścieżki plus ścieżkę w której chcemy instalować własne gemy, plik będzie wyglądać mniej więcej tak:

gempath:
 - /usr/lib/ruby/gems/1.8
 - /home/wijet/gems

Istotny jest format pliku, ponieważ jest interpretowany jako plik YAML.

Już możemy instalować własne gemy:

gem install rails -i /home/wijet/gems

Bardzo często wychodzą nowe wersje gemów, możemy hurtem przeprowadzać update gemów bez zawracania głowy adminowi.

gem update -i /home/wijet/gems