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
end

Zamiast 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
end

I można teraz napisać tak:

Post.filter(:category => 'ruby').clean_old_posts

Tags , ,  | 6 comments

Comments

  1. Avatar pnowak said 2 days later:

    czyli jak rozumiem bez problemu mozna integrowac sequel z RoR ?

  2. Avatar Jarosław Zabiełło said 2 days later:

    @pnowak: toż to cały tekst jest temu poświęcony. :)

  3. Avatar pnowak said 4 days later:

    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 ?

  4. Avatar Jarosław Zabiełło said 4 days later:

    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.

  5. Avatar Uzytkownik said 15 days later:
    Kod tworzÄ…cy DB jest chyba znacznie prostszy:
    
    DB = Sequel(YAML.load_file(config.database_configuration_file)[ENV['RAILS_ENV']])
    
    

    Nie jest to 100% kompatybilne (ale i podana metoda nie jest).

  6. Avatar pg said 23 days later:

    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.

(leave url/email »)

   Comment Markup Help Preview comment