Sequel vs Active Record. Część 2 - integracja Rails z Sequelem
Posted by Jarosław Zabiełło Fri, 21 Dec 2007 12:27:00 GMT
W pierwszej części trochÄ™ wypunktowaÅ‚em sÅ‚abe strony standardowego ORM’a używanego w Railsach. Najlepiej zastÄ…pić go szybszym i ogólnie dużo lepszym Sequelem. Można to zrobić na kilka sposobów: caÅ‚kowicie zastÄ…pić Active Record lub używać Sequela obok Active Record – jak kto woli.
Zakładam, że na początek może byśmy chcieli popróbować Sequela tak, aby można było szybko przełączyć się z powrotem na Active Record. Po doinstalowaniu gema sequel , należy przejść do pliku config/environment.rb i dodać gdzieś następujący kod:
require 'sequel'
DB = Sequel 'mysql://login:haslo@localhost/nazwa_bazy'Obiekt DB jest wielowątkowym połaczeniem z bazą definiowaną za pomocą URI. Jak ktoś, chce to można automatycznie zassać dane o bazie z pliku config/database.sql
require 'sequel'
conf = YAML.load_file(config.database_configuration_file)[ENV['RAILS_ENV']]
DB = Sequel "#{conf['adapter']}://#{conf['username']}:#{conf['password]}@#{conf['host']}/#{conf['database']}" Następnie w modelu można dodać sobie warunek tak, aby trzymać obie wersje kodu, dla AR i dla Sequela (potem można wywalić to, co nie jest potrzebne).
if DB
# Wersja dla Sequel
class Preference < Sequel::Model(:preferences)
def user
User.filter(:id => user_id)
end
end
else
# Wersja dla Active Record
class Preference < ActiveRecord::Base
belongs_to :user
end
endZamiast metody user można użyć makra one_to_one :user, :from => :User ale ja wolÄ™ stworzyć wÅ‚asnÄ… metodÄ™. Robi nie tylko to samo, ale także nie trzeba pamiÄ™tać dodatkowych opcji w razie nietypowej struktury. Poza tym w podanym przykÅ‚adzie zwracany jest obiekt proxy, a nie lista obiektów. Daje to możliwoÅ›ci poza zasiÄ™giem Active Record. MogÄ™ rozbudowywać zwracany obiekt o kolejne metody. Na każdym etapie mam podglÄ…d do wygenerowanego SQL’a.
Preference.first.user.sql
=> "SELECT * FROM users WHERE (`id` = 1)"
Preference.first.user.order(:name).sql
=> "SELECT * FROM users WHERE (`id` = 1) ORDER BY `name`"
Preference.first.user.order(:name).select(:users.all).sql
=> "SELECT users.* FROM users WHERE (`id` = 1) ORDER BY `name`"Albo inny przykład
class Post < Sequel::Model(:posts)
def dataset.old_posts
filter {:stamp < 30.days.ago}
end
def dataset.clean_old_posts
old_posts.delete
end
endI można teraz napisać tak:
Post.filter(:category => 'ruby').clean_old_posts

Kanały IRC![[Dilber w Onecie]](/images/larry.png)


czyli jak rozumiem bez problemu mozna integrowac sequel z RoR ?
@pnowak: toż to cały tekst jest temu poświęcony. :)
tak, wiem ale nie poruszono tutaj chocby tematow testowania, walidatorow itd. czy w rails sa zaszyste jakies zaleznosci z ar na stale ktore nie pozwola na korzystanie z sequel w pelnym zakresie ?
Generalnie Sequel preferuje podejÅ›cie minimalistyczne – czysty Ruby i mniej magii. Np. zaleca pisanie metod klasowych rozszerzajÄ…cych podstawowy model ORM zamiast polegania na makrach/helperach do tworzenia powiÄ…zaÅ„ relacyjnych. Co do walidatorów to jest validatable którego metody powinny dać siÄ™ wstrzyknąć do Sequela, ale siÄ™ tym nie bawiÅ‚em.
Kod tworzÄ…cy DB jest chyba znacznie prostszy:
Nie jest to 100% kompatybilne (ale i podana metoda nie jest).
Uzytkownik: niestety adapter MySQL w Sequelu wymaga :user zamiast :username, a poza tym wczytanie database.yml zwróci klucze w postaci String a nie Symbol, czego już Sequel nie przetrawi. Ja wykombinowalem coś takiego:
arc = ActiveRecord::Base.configurations[ENV['RAILS_ENV']].symbolize_keys DB = Sequel(arc,:user=>arc[:username])Przetestowane na Sequel 1.0.