Przegląd po zmianach w Rails 2.0
Wysłane przez Marek Tenus (~marcus) dnia 04.11.2007
Jak wiecie prace nad Rails 2.0 wciąż trwają. Zanim jednak pojawi się nowa wersja frameworka powinniśmy przyjrzeć się bliżej zmianom jakie w nim nastąpią w sosunku do wersji 1.2.X. Pewien czas temu pojawił się na weblogu serwisu rubyonrails.org przegląd po zmianach jakie wprowadzono do RoR. Autorzy zastrzegają sobie jadnak, że niektóre z opisanych elementów mogą ulec zmianie, lecz mogą to być najwyżej jakieś pomniejsze fixy lub ulepszenia.
Action Pack: Resources
Z pewnością większość z was używa Resources zwłaszcza pomocnych przy tworzeniu RESTowych API. Zmiany:- Usunięto średnik dla metod zdefiniowanych w kontrolerze przez developera i zastąpiono go slashem
- Dodano możliwość namespacesowania deklarowanych zasobów
Przed:
/people/1;edit
Po
/people/1/edit
map.namespace(:admin) do |admin| admin.resources :products, :collection => { :inventory => :get }, :member => { :duplicate => :post }, :has_many => [ :tags, :images, :variants ] end
Tak zdefiniowany zasób stworzy nam następująco nazwane marszruty (ang. routes)
inventory_admin_products_url admin_product_tags_url
Poza tym dodano nowe zadanie do rake'a "routes”, dzięki któremu możemy listować wszystkie nazwane marszruty zdefiniowane w routes.rb.
rake routes
# /avatars/45 => AvatarsController#show map.resources :avatars # /people/5/avatar => AvatarsController#show map.resources :people, :has_one => :avatar
Action Pack: MultiView
O zmianach w tym pakiecie możemy powiedzieć, że jest to dość ciekawy sposób uporządkowania dotychczasowych możliwośći tego pakietu. Pliki w View mają nową konwencję nazewnictwa:
action.format.renderer
co oznacza, że dla akcji index będziemy mogli stworzyć pliki o formatach:
//zamiast index.rxml index.atom.builder index.html.erb index.csv.erb index.html.haml ...
należy dodać, że wspólnym dla wszystkich formatów templatem jest plik index.erb. Dzięki wykorzystaniu respond_to możemy dość łatwo utworzyć template'y o danym formacie.
class UserController < ApplicationController def index respond_to do |format| format.html # renders index.html.erb format.csv # renders index.csv.erb end end
Poza tym możemy sami zadeklarować swój 'fake'owy (zafałszowany) typ mime dla wewnętrznego routingu. Dzięki czemu nie będzie wyrenderowany domyślny format template'a dla danego typu mime (dla iphone jest to haml, a poniżej zmienimy go na html).
# rejestracja przez siebie zdefiniowanego 'fake'owego typu mime # w config/initializers/mime_types.rb Mime.register_alias "text/html", :iphone class ApplicationController < ActionController::Base before_filter :adjust_format_for_iphone private def adjust_format_for_iphone if request.env["HTTP_USER_AGENT"] && request.env["HTTP_USER_AGENT"][/(iPhone|iPod)/] request.format = :iphone end end end
i możemy już użyć tego typu w naszym kodzie:
respond_to do |format| format.iphone # index.iphone.erb # zamiast index.iphone.haml end
bądź możemy zadeklarować swój własny typ mime:
# rejestracja przez siebie zdefiniowanego typu mime # w config/initializers/mime_types.rb Mime.register_alias "text/html", :yhml
Action Pack: Record identification
Poniżej przykład, który wam wszystko wyjaśni.
redirect_to(person) link_to(person.name, person) form_for(person)
Gdzie person jest tożsame z objektem Person zmapowanym w routes i do metody person_url
Action Pack: HTTP Loving
Nowy pakiet w Rails umożliwiający wygodną obsługę uwierzytelniania komunikacji poprzez HTTP. Poniższy przykład powinien powiedzieć wam o tym pakiecie wystarcająco dużo.
class UserController < ApplicationController USER_NAME, PASSWORD = "marek", "hasło_marka" before_filter :authenticate, :except => [ :index ] def index render :text => "Strefa dostępna dla każdego" end def edit render :text => "Znasz hasło więc masz tu dostęp" end private def authenticate authenticate_or_request_with_http_basic do |user_name, password| user_name == USER_NAME && password == PASSWORD end end end
Też macie wrażenie, że zaskakująco proste i bezpieczne? Więcej możliwości możecie poznać zaglądając do ActionController::HttpAuthentication. Warto wspomnieć też o obsłudze assetów. Czyli możliwości zaciągania css, js, grafiki z innych hostów (co znacznie przyśpiesza ich ściąganie a tym samym ładownie w przeglądarce).
ActionController::Base.asset_host = “assets%d.ruby-on-rails.pl”
Dzięki powyższej deklaracji pliki graficzne naprzykład przy ładowaniu z użyciem image_tag (tzw. assetowych callerów) będą zaciągane z kilku źródeł/aliasów (pomimo, że pliki znajdują się nawet w tym samym katalogu). Obsuga assetów została wprowadzona zapewne po wynikach badań przeprowadzonych przez Yahoo. Szybkość ładowania takich aplikacji zwiększyła się prawie dwukrotnie. Proponuję przeczytać więcej tutaj. Zastanawiące jest tylko, dlaczego tworzone są 4 assety pomimo, że badania Yahoo Team'u pokazują, że najbardziej optymalne wydaje się użycie tylko dwóch. Widocznie team Rails ma większą wiedzę na ten temat..
Action Pack: Security
W tym pakiecie głównie zwiększono zabezpieczenia przed atakami CRSF i XSS. Zabezpieczniem przed CRSF ma być dodawany specjalny token do formularzy i Ajaxowych zapytań. Przed atakami XSS będzie nas chroniła ulepszona wersja metody TextHelper#sanitize. Do tej pory istniała tylko black lista dla tej metody, przez co jej użycie często było niemożliwe, dlatego też wprowadzono white list'e, w której można definiować, które tagi są dopuszczalne.
Action Pack: Exception handling
Zmiana w tym pakiecie bardzo mi się spodobała. Będzie możliwa prosta obsługa danego wyjątku pd danym typie z poziomu metody danego kontrolera. Nie będziecie już musieli używać rescue_action_in_public. Wystarczy skorzystać z makra rescue_from.
class UserController < ApplicationController rescue_from User::NotAuthorized, :with => :deny_access protected def deny_access ... end end
Action Pack: Miscellaneous
Rozbudowano w tym pakiecie możliwości obsług formatu Atom (AtomFeedHelper). Jest ona jeszcze prostsza i wygodniejsza.
# index.atom.builder: atom_feed do |feed| feed.title("Mój blog!") feed.updated((@posts.first.created_at)) for post in @posts feed.entry(post) do |entry| entry.title(post.title) entry.content(post.body, :type => 'html') entry.author do |author| author.name("marcus") end end end end
Poza tym usunięto in_place_editor i autocomplete_for i przeniesiono je do odpowiednich pluginów.
Active Record: Performance
Tutaj dość mała zmiana, choć czasami może się okazać przydatną w naszym projekcie. Dodano bardzo prosty Query Cache dla zapytań SQL. Nie jest to coś niesamowitego, ale zawsze lepsze coś niż nic..
Active Record: Sexy migrations
Zmieniono konwencję kodowania migracji (czy są one sexy sami oceńcie ;) )
# Obecnie byśmy napisali create_table :people do |t| t.column, "account_id", :integer t.column, "first_name", :string, :null => false t.column, "last_name", :string, :null => false t.column, "description", :text t.column, "created_at", :datetime t.column, "updated_at", :datetime end # a już niedługo będziemy pisali create_table :people do |t| t.integer :account_id t.string :first_name, :last_name, :null => false t.text :description t.timestamps end
Active Record
XML zamiast JSON'a
person = Person.new # deserializacja z XML person.from_xml(“Marek“) # serializacja do JSON'a z ta samą składnią, jaka występuję przy serializacji do XML person.to_json
Pozbycie się pewnego balastu
Usunięto acts_as_XYZ przenosząc je do odpowiedniego pluginu. Jeśli więc będziemy chcieli użyć act_as_list musimy przedtem zainstalować potrzebny nam plugin.
script/plugin install acts_as_list
Pozostawiono jedynie adaptery dla baz danych MySQL, SQLite i PostgreSQL. Jeśli będziecie chcieli użyć naprzykład bazy Oracle w swoim projekcie, będziecie musieli doinstalować sobie odpowiedni adapter (activerecord-nazwa_bazy-adapter):
gem install activerecord-oracle-adapter
with_scope jako metoda protected
ActiveResource zamiast ActionWebService
Trochę mnie ta zmiana martwi (osobiście wolę, aby SOAP i REST współistniały w Railsach razem). Wogóle nie podoba mi się tutaj podejście teamu Railsowego do SOAP. Zawsze jednak będziemy mogli użyć pluginu :) :
gem install actionwebservice
"Wrócił" debugger
Whoaa.. W końcu coś ciekawego. W pełni funkcjonalny i "prawdziwy" debugger jak na możliwości "aplikacji przeglądarkowych". Możemy ustawiać breakpoint'y, śledzić każdą linię kodu.. a wystarczy jedynie zainstalować plugin ruby-debug.
gem install ruby-debug
Lepsza konfigurowalność aplikacji
Pojawił się config/initializers, gdzie możemy umieszczać nasze pliki konfiguracyjne (będą one ładowane automtycznie). Nie będziemy musieli już wszystkie nasze ustawienia umieszczać w config/environment.rb lub tworzyć własnych struktur
Prostsze porządkowanie pluginów
Zmiana z pewnością przydatna przy plugnowości Rails 2.0. Będziemy mogli sobie definiować kolejność ładowania pluginów (w config.plugins).
# najpierw załaduj plugin act_as_list a potem pozostałe config.plugins = [ :acts_as_list, :all ]
Podsumowanie
Z pewnością możemy stwierdzić, że Rails 2.0 bardziej zrobi krok w przód niż do tyłu. Co do niektórych zmian możemy mieć wątpliwości, lecz dopiero przy pisania większego projektu będziemy mogli w pełni je sprawdzić i ocenić. Osobiście uważam, że odchodzenie od SOAP w tak znaczący sposób nie dokońca mi się podoba. Z pewnością powyższe zmiany powinny wpłynąć na bezpieczeństwo i wydajności aplikacji oraz poprawić jakość naszej pracy. Pluginowość (nie modułowość!!) Railsów uważam za strzał w dziesiątkę no i ten debugger.. . Ogólnie mogę stwierdzić, że zmiany są na 4+. Prawdopodobnie prace nad Rails 2.0 skończą się w marcu/kwietniu 2008 roku.
Warto przeczytać
Ocena zmian w Rails 2.0Preparing for Rails 2.0
