Forum poświęcone Ruby on Rails i językowi programowania Ruby
Nie jesteś zalogowany.
Nadchodzące w ActiveRecord zmiany zwiastują niemałą rewolucje. Oczywiście zanim rewolucja nastąpi czeka nas jeszcze wydanie Rails 3.1 gdzie pojawią się wszystkie ostrzeżenia dotyczące metod które wylecą (a wylatuje ich naprawde dużo). Myśle ze w Rails 3.2 przestanie działać 99 % obecnych pluginów. Nowy system relacji mi sie podoba, przypomina to co prezentował Sequel ale wydaje sie być jeszcze bardziej niskopoziomowy (Sequel zawierał już wiele uproszczeń, tutaj tych uproszczeń nie ma).
Po więcej odsyłam tutaj:
http://m.onkey.org/2010/1/22/active-rec … -interface
Tymczasem jeśli ktoś chce spróbować to należy:
1. Zainstalowac thor'a
2. Ściągnąć edge rails (git://github.com/rails/rails.git) i zbudować gem'y (rake package) i zainstalowac activesupport, activemodel, activerecord (wszystkie gem'y po zbudowaniu powinny byc w kataogach pkg)
3. Ściągnąc edge Arel (git://github.com/rails/arel.git) i zbudować gem (thor package) i zainstalować (gem install pkg/arel-2.0.pre.gem)
Przykładowy kod żeby wszystko ze sobą spiąć (dla MySQL):
require 'rubygems'
require 'arel'
require 'active_record'
require 'logger'
ActiveRecord::Base.logger = Logger.new('arel.log')
ActiveRecord::Base.configurations = {
'sd' => {
:adapter => 'mysql',
:username => 'root',
:encoding => 'utf8',
:database => 'baza',
}
}
ActiveRecord::Base.establish_connection 'sd'
Arel::Table.engine = Arel::Sql::Engine.new(ActiveRecord::Base)Osobiście bardzo podoba mi się nowy system budowania zapytań. Oto prosty przykład budowania relacji tabeli users z tabelą locations i prostego warunku OR:
users = Table(:users)
locations = Table(:locations)
query = users.join(locations).on(users[:location_id].eq(locations[:id])).where(users[:name].eq('pkondzior').or(users[:name].eq('rgrabowski')))Okres przejściowy będzie naprawde trudny dla wielu aplikacji, ale myśle ze nowy system usprawni mocno pisanie złożonych zapytań i warunków. Każde takie zapytanie można bez problemu enumerować, dobudowywać kolejne jego części lub po porstu zamienić na sql metodą #to_sql. Jest też możliwość dopiywania opcji poprzez Hash #apply_finder_options jeśli ktoś już naprawde będzie musiał ![]()
Offline
Dodam tylko ze wzoruja sie chyba na API SQLAlchemy z pythona.
Offline
Jeszcze w temacie.. przykład użycia nowego API w Model'ach wygląda jak narazie troche topornie:
Location.where(Location.arel_table[:name].eq("Washington")).to_sql
=> SELECT `locations`.* FROM `locations` WHERE (`locations`.`name` = 'Washington')Offline
PaK napisał:
przykład użycia nowego API w Model'ach
nie kombinuj za mocno: "przykład użycia nowego API w modelach" wygląda zdecydowanie lepiej
.
Co do tych wszystkich nowinek, to jest to fajne że starają się schować głębiej SQL. A jak to na prawdę będzie działać to zobaczymy.
Offline
PaK napisał:
Jeszcze w temacie.. przykład użycia nowego API w Model'ach wygląda jak narazie troche topornie:
Kod:
Location.where(Location.arel_table[:name].eq("Washington")).to_sql => SELECT `locations`.* FROM `locations` WHERE (`locations`.`name` = 'Washington')
Ja cały czas właśnie czekam na jakąś sensowną propozycję conditions zrobione w ActiveRecord (tzn. bez instalowania pluginów i ze wsparciem rails core team), które pozwolą na OR bez uciekania do stringów.
Offline
drogus napisał:
Ja cały czas właśnie czekam na jakąś sensowną propozycję conditions zrobione w ActiveRecord (tzn. bez instalowania pluginów i ze wsparciem rails core team), które pozwolą na OR bez uciekania do stringów.
Czekam na to samo... i zapowiada sie obiecująco. Perspektywa Arel wygląda to przejrzyście:
users = Table(:users)
users.project(users[:id]).where(users[:name].eq("pkondzior").or(users[:name].matches("%grabowski%")).and(users[:active].eq(true))).to_sql
=> "SELECT `users`.`id` FROM `users` WHERE ((`users`.`name` = 'pkondzior' OR `users`.`name` LIKE '%grabowski%') AND `users`.`active` = 1)"Ale ActiveRecord ma to troche dziwnie obudowane:
User.where(User.arel_table[:name].eq("pkondzior").or(User.arel_table[:name].matches("%grabowski%")).and(User.arel_table[:active].eq(true))).to_sql
=> "SELECT `users`.* FROM `users` WHERE (((`users`.`name` = 'pkondzior' OR `users`.`name` LIKE '%grabowski%') AND `users`.`active` = 1))"Natomiast naprawde topornie jest obecnie przepisywany Hash na Arel:
User.where(:name => 'pkondzior')
Przechodzi w:
User.where(Arel::Attribute.new(User.unscoped, :name).eq("pkondzior")).to_sql
=> "SELECT `users`.* FROM `users` WHERE (`users`.`name` = 'pkondzior')"Nie mam pojęcia dlaczego obecnie jest to generowane właśnie w taki sposób. Chyba aktualnie nie mają jeszcze pomysłu jak udostępnić nowe API Arel w ActiveRecord
Offline
PaK napisał:
Kod:
User.where(:name => 'pkondzior')Przechodzi w:
Kod:
User.where(Arel::Attribute.new(User.unscoped, :name).eq("pkondzior")).to_sql => "SELECT `users`.* FROM `users` WHERE (`users`.`name` = 'pkondzior')"Nie mam pojęcia dlaczego obecnie jest to generowane właśnie w taki sposób. Chyba aktualnie nie mają jeszcze pomysłu jak udostępnić nowe API Arel w ActiveRecord
Ale syf. Przypominają mi się czasy php i propela. Jeśli coś takiego miałoby zostać to... nie wiem co powiedzieć. Zaczynam wierzyć w koniec świata w 2012 roku
.
Offline
radarek napisał:
PaK napisał:
Kod:
User.where(:name => 'pkondzior')Przechodzi w:
Kod:
User.where(Arel::Attribute.new(User.unscoped, :name).eq("pkondzior")).to_sql => "SELECT `users`.* FROM `users` WHERE (`users`.`name` = 'pkondzior')"Nie mam pojęcia dlaczego obecnie jest to generowane właśnie w taki sposób. Chyba aktualnie nie mają jeszcze pomysłu jak udostępnić nowe API Arel w ActiveRecord
Ale syf. Przypominają mi się czasy php i propela. Jeśli coś takiego miałoby zostać to... nie wiem co powiedzieć. Zaczynam wierzyć w koniec świata w 2012 roku
.
Warto chyba nadmienić, że ten kod to "niskopoziomowy" framework Arel z którego ma korzystać ActiveRecord więc użytkownik Rails'ów nieczęsto będzie musiał bezpośrednio z niego korzystać (w domyśle tak często jak teraz korzysta z find_by_sql np.) IMO chodzi o wyeliminowanie budowania zapytań sklejając ze sobą stringi, które jest obecnie w kodzie AR opierając framework AR na frameworku Arel - czy coś pomieszałem ?
Wg. mnie będzie lepiej o ile jakimś dziwnym trafem nie zostaniemy zmuszeni do korzystania z API przypominającego JPA (patrząc na to co się dzieje z Rails 3 i w którą stronę wszystko zmierza jestem przekonany, że nie zostaniemy zmuszeni
)
Offline
hosiawak napisał:
Warto chyba nadmienić, że ten kod to "niskopoziomowy" framework Arel z którego ma korzystać ActiveRecord więc użytkownik Rails'ów nieczęsto będzie musiał bezpośrednio z niego korzystać (w domyśle tak często jak teraz korzysta z find_by_sql np.) IMO chodzi o wyeliminowanie budowania zapytań sklejając ze sobą stringi, które jest obecnie w kodzie AR opierając framework AR na frameworku Arel - czy coś pomieszałem ?
Wg. mnie będzie lepiej o ile jakimś dziwnym trafem nie zostaniemy zmuszeni do korzystania z API przypominającego JPA (patrząc na to co się dzieje z Rails 3 i w którą stronę wszystko zmierza jestem przekonany, że nie zostaniemy zmuszeni
)
Dokładnie tak. Wszystko co do tej pory można było robic z find() będzie nadal dostępne pod postacią where() z tą różnicą że będzie to tłumaczone na zapytanie dopiero w bibliotece ARel a nie tak jak do tej pory w ActiveRecord. Już teraz kod AR jest w owiele lepszym staniem IMHO po podłączeniu tego ARel, AR 3.2 będzie już zupełnie innym ActiveRecord.
Te przykłady które podałem to nie jest ZALECANE stosowanie, to jest coś co ja wyciągnołem z kodu żeby pokazać jak to mniejwięcej teraz działa. Ja osobiście mam nadzieje ze nowe API podniesie troche jakość złożonych zapytań i edge cases przestaną wyratać jak grzyby po deszczu
No ale pewnie jestem tutaj zbyt dużym optymistą....
Offline
radarek napisał:
PaK napisał:
Kod:
User.where(:name => 'pkondzior')Przechodzi w:
Kod:
User.where(Arel::Attribute.new(User.unscoped, :name).eq("pkondzior")).to_sql => "SELECT `users`.* FROM `users` WHERE (`users`.`name` = 'pkondzior')"Nie mam pojęcia dlaczego obecnie jest to generowane właśnie w taki sposób. Chyba aktualnie nie mają jeszcze pomysłu jak udostępnić nowe API Arel w ActiveRecord
Ale syf. Przypominają mi się czasy php i propela. Jeśli coś takiego miałoby zostać to... nie wiem co powiedzieć. Zaczynam wierzyć w koniec świata w 2012 roku
.
Dramatyzujesz
pokazałem tylko jak obecnie AR składa zapytania
Jeśli tylko znajdą sposób na łatwiejsze przedstawianie tych atrybutów ARel w kodzie AR to nie będzie tak źle. Jeśli byś wzioł teraz Ruby TreeParser to napisanie zajebiste DSL'a na bazie czegoś takiego staje sie 100x prostrze
To samo tyczy sie każdej innej biblioteki typu Squirrel, Searchlogic które zazwyczaj wymyślały swoje mechanizmy łączenia kodu SQL od nowa.
Offline
PaK, przecież napisałeś że to przykład użycia nowego API w modelach :>. Zmyliłeś mnie.
Offline
radarek napisał:
PaK, przecież napisałeś że to przykład użycia nowego API w modelach :>. Zmyliłeś mnie.
Przykład użycia nowego API Arel z poziomu Modelu ![]()
Model#arel_table, Model#arel_engine nie należa jeszcze do oficjalnego API ActiveRecord, to samo tyczy sie chyba Model#unscoped. Natomiast Arel::Attribute.new(Model#unscoped, :column_name) to już API ARel z wykorzystaniem ActiveRecord, faktycznie troche nieprecyzyjny byłem wcześniej
moja wina.
Offline
Nick Kallen, jeden z programistów Twitter'a opisuje dlaczego powstał Arel
Offline
Mnie zastanawia tylko następująca sprawa:
Załóżmy:
class Author < ActiveRecord::Base
has_many :books
end
class Book < ActiveRecord::Base
belongs_to :author
end
Dawniej mogłem zapytać:
Book.all(:joins => :author, :conditions =>{:author =>{:lastname => "King"}})
Teraz trzeba będzie:
Book.join(authors).on(authors[:id].eq(books[:author_id])).where(authors[:lastname].eq("King"))
Czyli 1) musze podać warunek złączenia
2) zapis jest dłuższy i wcale nie bardziej czytelny
Chyba, że da się to zapisać inaczej
Ostatnio edytowany przez wpasternak (2010-02-13 22:34:16)
Offline
@wpasternak: doczytaj ostatni post PaK'a i skup się na tym poście: http://m.onkey.org/2010/1/22/active-rec … -interface ![]()
Offline
fastred napisał:
@wpasternak: doczytaj ostatni post PaK'a i skup się na tym poście: http://m.onkey.org/2010/1/22/active-rec … -interface
Zaraz będe testował - sama idea AREL wydaje się trafiona w 10 - trzeba bedzie tylko pewnie poczekać aż dograją na tip -top składnie no i troche się pomęczyć przy przestawieniu na nowy zapis
Offline
Testowałem: Da się zapisać tak:
Book.joins(:author).where(:authors =>{:lastname =>"King"}).all
Dla mnie git ![]()
Offline
Nie wiem czym tu się jarać. Znacznie większe możliwości ma Sequel. M.in. ma ładniejszy i potężniejszy DSL (sumy logiczne to żaden tam problem), ma prepared statement (znacznie przyśpiesza niektóre operacje i automatycznie znika możliwość SQL injection), ma bardzo wygodną metodę .sql którą można dokleić w dowolnym etapie budowania zapytania aby wyświetlić jaki ostateczny SQL zostanie stworzony (i to się wyświetli bez jakiegokolwiek łączenia się z bazą!). Ma też eager preloading, transakcje, sharding i inne zaawansowane mechanizmy bazy relacyjnej itp. itd.
Offline
Jarek, ale wszyscy śledzący blog Yehudy i komentarze nań już wiedzą, że jesteś niezbyt pozytywnie nastawiony do Rails 3 od strony nawet samej idei, nie wspominając o poszczególnych rozwiązaniach ![]()
Ostatnio edytowany przez Tomash (2010-02-14 06:50:32)
Offline
Nie wiem czym tu się jarać.
Prawdopodobnie tym, że jedna z najpopularniejszych (żeby nie było flame'u: najpopularniejsza != najlepsza) bibliotek do obsługi bazy danych w Ruby dostanie genialne API i jest gruntownie zrefaktoryzowana. Większość osób tutaj po prostu już używa ActiveRecorda i przesiadka na innego ORMa będzie trudniejsza niż na kolejną wersję AR. W pierwszym przypadku musisz od razu przepisać cały kod, w drugim powoli poprawiać wszystkie deprecation warnings.
Offline
Tylko jak zapisać po nowemu takie zapytanie (Postgres)
select authors.lastname, count(books.id) as bcnt
from authors inner join books on
books.author_id = authors.id
group by authors.lastname
having count(books.id) > 10;
No i jeszcze sprawa z metodą project - zwraca obiekt project, z którym nie bardzo umiem cokolwiek zrobić
Ostatnio edytowany przez wpasternak (2010-02-14 10:48:44)
Offline
wpasternak napisał:
Tylko jak zapisać po nowemu takie zapytanie (Postgres)
select authors.lastname, count(books.id) as bcnt
from authors inner join books on
books.author_id = authors.id
group by authors.lastname
having count(books.id) > 10;
No i jeszcze sprawa z metodą project - zwraca obiekt project, z którym nie bardzo umiem cokolwiek zrobić
W ARel bedzie to pewnie cos takiego:
locations = Table(:locations) clients = Table(:clients) locations.join(clients).on(locations[:client_id].eq(clients[:id])).project(locations[:name], clients[:id].count).group(locations[:name])
Tylko jest to bez HAVING, jeszcze nie wykombinowałem jak tego używac, i nazwy tabel i kolumn są inne. Oczywiście to jest kod ARel nie AR
i tutaj właśnie pojawiają się schody, używanie ARel w AR wygląda mało przyjemnie, a nie wszystko będzie można osiągnąć prostym symbolem albo hashem.
Offline
Tomash napisał:
Jarek, ale wszyscy śledzący blog Yehudy i komentarze nań już wiedzą, że jesteś niezbyt pozytywnie nastawiony do Rails 3 od strony nawet samej idei, nie wspominając o poszczególnych rozwiązaniach
Jarek jest negatywnie nastawiony od pierwszej godziny po ogłoszenia przez DHH i Wycats'a nowiny o połączeniu zespołów.
Offline
hipertracker napisał:
Nie wiem czym tu się jarać. Znacznie większe możliwości ma Sequel. M.in. ma ładniejszy i potężniejszy DSL (sumy logiczne to żaden tam problem), ma prepared statement (znacznie przyśpiesza niektóre operacje i automatycznie znika możliwość SQL injection), ma bardzo wygodną metodę .sql którą można dokleić w dowolnym etapie budowania zapytania aby wyświetlić jaki ostateczny SQL zostanie stworzony (i to się wyświetli bez jakiegokolwiek łączenia się z bazą!). Ma też eager preloading, transakcje, sharding i inne zaawansowane mechanizmy bazy relacyjnej itp. itd.
Wszystko sie zgadza. Jest jedno ALE, musisz przepisać każdą swoją aplikacje na nowa biblioteke, a nie wzystko w Sequelu działa tak pięknie jak w AR. Tutaj masz jeszcze odpowiedź Evansa na argumenty Nick'a dlaczego ARel a nie Sequel. http://sequel.heroku.com/2010/02/06/are … es-part-1/ w poscie jest też link do tego co pisał Nick wcześniej. Ogólnie, ARel wejdzie do Rails prawie że transparentnie. Dopiero w 3.1 ma się zmienić API na tyle że będzie naprawde widać różnice. Nie osiągniesz tego w używając Sequela. Pozatym jest tu jeszcze problem ActiveSupport. IMHO ta biblioteka po prostu musiała powstać od nowa z myślą tylko i wyłącznie o AR.
Offline
To ja na razie podziękuje za ten nowy ActiveRecord i przywitam się z DataMapperem - ale mam nadzieję, że koniec końców stanie się to używalne
Offline