Ruby on Rails
![]() Logo programu | |
![]() | |
Autor | Rails Core Team |
---|---|
Pierwsze wydanie | lipiec 2004 |
Aktualna wersja stabilna | 7.2.0 (10 sierpnia 2024) [±] |
Język programowania | Ruby |
System operacyjny | Wieloplatformowy |
Rodzaj | Framework |
Licencja | MIT |
Strona internetowa |
Ruby on Rails (potocznie nazywany RoR lub Rails) – framework open source do szybkiego tworzenia aplikacji webowych. RoR został napisany w języku Ruby z użyciem architektury MVC (ang. Model-View-Controller). Pierwotnym autorem jest duński programista David Heinemeier Hansson, który w 2003 roku rozpoczął pracę nad frameworkiem w trakcie rozwijania narzędzia do zarządzania projektami Basecamp. W 2004 roku wyodrębnił on kod RoR z kodu Basecamp i oficjalnie wydał jako otwarte oprogramowanie[1].
Główne założenia
- szybkość, łatwość i przyjemność pisania kodu,
- reguła DRY (ang. Don't Repeat Yourself), polegająca na unikaniu powtarzania tej samej pracy w różnych miejscach,
- reguła Convention Over Configuration, polegająca na sprowadzeniu do minimum niezbędnej konfiguracji przez zastępowanie jej gotowymi domyślnymi, zalecanymi wzorcami,
- możliwość użycia wtyczek, które w sposób błyskawiczny rozszerzają aplikacje o rozmaite funkcje, jak logowanie, przesyłanie i skalowanie obrazków, czy tagowanie.
Historia wersji
Wersja | Data wydania | Uwagi |
---|---|---|
1.0[2] | 13 grudnia 2005 | Pierwsza stabilna wersja |
1.2[3] | 19 stycznia 2007 | |
2.0[4] | 7 grudnia 2007 | |
2.1[5] | 1 czerwca 2008 | Wsparcie dla stref czasowych, śledzenie zmian w modelu (dirty tracking), nazwane scope'y, zarządzanie zależnościami gemów |
2.2[6] | 21 listopada 2008 | internacjonalizacja, wsparcie dla Ruby w wersji 1.9 oraz JRuby |
2.3[7] | 16 marca 2009 | Działanie oparte na Racku, zagnieżdżone formularze, engine'y |
3.0[8] | 29 sierpnia 2010 | Nowa składnia zapytań ActiveRecord, użycie bundlera do zarządzania zależnościami, zabezpieczenie przed atakami typu XSS, fuzja kodu Ruby on Rails z kodem Merba |
3.1.1[9] | 7 października 2011 | jQuery jako domyślna biblioteka JavaScript, włączenie CoffeeScriptu i Sassa do domyślnej konfiguracji |
3.2[10] | 20 stycznia 2012 | Poprawiony moduł routingu, wsparcie dla Ruby 2.0 (od wersji 3.2.12), ostatnia wersja wspierający Ruby 1.8 |
4.0[11] | 25 lipca 2013 | Wprowadzenie Turbolinks |
4.1[12] | 8 kwietnia 2014 | Wprowadzenie Springa, wariantów szablonów, enumeratorów |
4.2[13] | 19 grudnia 2014 | Wprowadzenie ActiveJob, Adequate Record, Web Console oraz wbudowanego wsparcia dla bazodanowych kluczy obcych |
5.0[14] | 30 czerwca 2016 | Wprowadzenie ActionCable (framework do WebSockets), wprowadzenie możliwości wygenerowania szkieletu aplikacji typu API |
5.1[15] | 27 kwietnia 2017 | Zmiany dotyczące JavaScript (możliwość wygenerowania konfiguracji Webpacka, usunięcie jQuery jako wymaganej zależności), wprowadzenie szyfrowania „sekretów” aplikacji |
5.2[16] | 9 kwietnia 2018 | ActiveStorage (wbudowane rozwiązanie do obsługi wgrywania plików), obsługa Early Hints z HTTP/2, Redis Cache Store (narzędzie ujednolicające obsługę cache) |
6.0[17] | 15 sierpnia 2019 | ActionText (zintegrowany wzbogacony edytor tekstu), ActionMailbox (narzędzie do obsługi przychodzących maili), poprawiona obsługa wielu baz danych, wsparcie dla zrównoleglania testów, nowy reloader kodu |
6.1[18] | 9 grudnia 2020 | Ulepszenia pod kątem baz danych, np. wprowadzenie możliwości przełączania połączeń dla każdej bazy danych. Wprowadzono też przyspieszone ładowanie wszystkich asocjacji, typy delegowane, obiekty błędów, asynchroniczne usuwanie asocjacji |
7.0[19] | 15 grudnia 2021 | |
7.1[20] | 5 października 2023 | |
7.2[21] | 10 sierpnia 2024 | Wbudowane wsparcie dla development containers |
Budowa
Framework Ruby on Rails składają się z następujących elementów:
- ActiveRecord – mechanizm ORM (Object-Relational mapping) dla Ruby, odpowiedzialny za komunikację z bazami danych i persystencję
- ActiveModel – odpowiada za tworzenie modeli w architekturze MVC
- ActionPack – komponent odpowiedzialny za obsługę zapytań i odpowiedzi HTTP, definiuje m.in. kontrolery poprzez klasę ActionController
- ActionView – warstwa widoku w modelu MVC
- ActiveSupport – zbiór użytecznych dodatków do standardowej biblioteki Ruby, zawiera m.in. rozszerzenia klas String czy Time
- ActionMailer – biblioteka służąca do wysyłania wiadomości email (najczęściej przez aplikację Rails)
- ActiveJob – interfejs służący do definiowania prac w tle, odbywających się poza cykle zapytanie-odpowiedź
- ActionCable – komponent do obsługi technologii WebSocket
- ActiveStorage – komponent do obsługi wgrywania i przechowywania plików
- ActionText – framework do tworzenia zaawansowanych edytorów tekstu na stronach internetowych, oparty o otwarty edytor Trix
Każda z tych części może zostać zainstalowana oddzielnie, np. za pomocą menadżera pakietów RubyGems. W skład dystrybucji Rails wchodzi też konsolowy program rails, który generuje drzewo katalogów nowego projektu.
Serwer
Działanie aplikacji napisanej z użyciem Rails oparte jest na odpowiednim serwerze aplikacji. Dawniej domyślnym serwerem był WEBrick(inne języki), obecnie railsy instalują Pumę(inne języki). Raz uruchomiony serwer przypisuje nadchodzące żądania (requests) odpowiednim kontrolerom i na podstawie ich działania zwraca do klienta odpowiedź (response).
Serwer Rails może działać samodzielnie (nie jest to efektywne, więc bardzo rzadko stosowane), jednak najczęściej podłącza się do niego serwer HTTP jak Apache, Phusion Passenger czy Nginx. Zewnętrzny serwer równoważy wtedy obciążenie wszystkich serwerów aplikacji, serwuje pliki statyczne (css, js itd.), zabezpiecza przed atakami DDoS.[22]
Sposób działania
Rails oparte jest o architekturę MVC, tzn. klient po wyświetleniu widoku (w tym przypadku wygenerowanej strony HTML), wysyła do aplikacji żądanie (klikając w odpowiedni link na stronie lub wypełniając formularz). Żądanie jest przyjmowane przez kontroler, który generuje odpowiedź w formie widoku wysyłanego do klienta (najczęściej kontroler w celu wygenerowania odpowiedzi pobiera dane z modelu, który w Rails implementowany jest jako relacyjna baza danych). Poniżej szczegółowo omówiono mechanizmy odpowiedzialne w Rails za model MVC.
Model
Modele w Ruby on Rails reprezentowane są przez klasy, zdefiniowane w plikach znajdujących się w katalogu app/models
. Najczęściej spotyka się aplikacje używające dostarczanego razem z frameworkiem ORM-a ActiveRecord, przeznaczonego do baz relacyjnych. Modele mogą jednak korzystać również z baz nierelacyjnych (np. MongoDB[23]), a do komunikacji z bazami relacyjnymi używać innych bibliotek (Sequel[24], DataMapper[25] czy ROM[26]). Klasa modelu może również w ogóle nie być powiązana z żadną bazą, a stanowić jedynie jednostkę logiki biznesowej aplikacji.
ActiveRecord
ActiveRecord jest ORM-em używanym domyślnie m.in. w generatorze szkieletu aplikacji Ruby on Rails. Klasy modeli dziedziczą po klasie bazowej ActiveRecord::Base
. Nazwa tabeli, o ile nie jest podana jawnie, zostaje „odgadnięta” na podstawie nazwy klasy. Poszczególne kolumny tabeli są dostępne w obiektach modelu jako metody/atrybuty
Oto przykład jaki kod można napisać dysponując w bazie danych przedstawioną tabelą users:
id (INTEGER) | name (VARCHAR) | created_at (DATETIME) |
---|---|---|
1 | Adam | 2007-01-14 22:07:13 |
2 | Ewa | 2007-01-05 13:56:48 |
class User < ActiveRecord::Base end User.count # => 2 adam = User.find(1) adam.name # => "Adam" ewa = User.find_by_name "Ewa" ewa.created_at.to_s # => "Fri Jan 05 13:56:48 +0100 2007" jacek = User.new jacek.name = "Jacek" if jacek.save # zapis do bazy danych się udał User.count == 3 # => true else # wystąpiły błędy, np. pole oznaczone jako NOT NULL nie ma w obiekcie przypisanej żadnej wartości end
Część pól zostaje przez ActiveRecord wypełniona automatycznie. Są to pola (o ile istnieją takie kolumny w tabeli bazy danych) created_at/created_on
(kiedy rekord został utworzony) oraz updated_at/updated_on
(kiedy został ostatnio zmieniony)[27]. Standardowo każda tabela przeznaczona do pracy z ActiveRecord powinna mieć kolumnę id
typu INTEGER, która jest kluczem głównym.
W klasach definiujących modele możemy określać zachodzące pomiędzy modelami relacja (jeden do jednego, jeden do wielu itp.), wymagania dotyczące rekordów (np. długość hasła) czy funkcje zwrotne (ang. callbacks), wywoływane m.in. przy zapisie danych do bazy[28]. Można też dodawać inną funkcjonalność, jak np. metoda sprawdzająca na podstawie imienia czy użytkownik jest mężczyzną czy kobietą:
class User < ActiveRecord::Base # ... def is_male? name.last != "a" # jeżeli tak, zwróci true end # ... end
Widoki – ActionView, RHTML
Klasa ActionView odpowiedzialna za widoki definiuje wiele pomocniczych metod, pozwalających generować kod HTML, np.:
link_to "Usuń użytkownika", { :action => "destroy", :id => @user.id }, :confirm => "Jesteś pewien?" form_tag({:controller=>'user', :action=>'search'}, :method=>'get')
Widoki pisze się w plikach *.html.erb, które zawierają przemieszany kod HTML i Ruby. Tak przygotowany szablon interpretowany jest przez program ERB (Ruby Embedded), który działa podobnie do parsera PHP. Dzięki temu kod HTML może być np. generowany w pętli. Jeden widok odpowiada zazwyczaj jednej akcji kontrolera. Widoki na ogół osadzane są w jednolitym dla strony szablonie (ang. layout), do którego wstawia się wynik działania poszczególnych akcji.
Kontrolery – ActionController
Logika aplikacji zawarta jest w kontrolerach – klasach dziedziczących po ApplicationController. Każdy kontroler definiuje określony zbiór akcji (w Rails są to publiczne metody klas kontrolerów), który definiuje jego funkcjonalność. Jeden kontroler zazwyczaj skupia się na wykonaniu zadań z konkretnej dziedziny działania aplikacji. Oto jak mógłby wyglądać przykładowy kontroler do zarządzania kontami użytkowników:
class UserController < ApplicationController def index redirect_to :action => :greet # przykład przekierowanie do innej akcji end def greet @user = User.find(session[:user_id]) # dostęp do danych zapisanych w sesji # ta prosta akcja nie wymaga więcej od kontrolera, # zmienna @user zostanie udostępniona widokowi, # który wygeneruje powitanie dla użytkownika (np. witając po imieniu) end def destroy @user = User.find(params[:id]) # parametr nadesłany metodą GET lub POST (bez znaczenia w tym przypadku) @user.destroy flash[:message] = "Użytkownik usunięty" # pamięć podręczna dostępna później w widoku dowolnej akcji redirect_to :home_url # adres zdefiniowany w pliku routes.rb, zmiana adresu strony domowej nie wpłynie na działanie kontrolera end protected # poniższe metody nie są publiczne, więc nie są akcjami def check_user # dowolne działania, z których korzysta więcej niż jedna akcja # powinny zostać wydzielone do osobnej metody zgodnie z regułą DRY end end
Metoda index w tym przypadku przekierowuje żądanie do innej akcji, metoda greet pobiera dane z modelu i przekazuje je dalej (bez większej obróbki) do widoku. Metoda destroy dokonuje zmian w danych pobranych z modelu po czym oddaje sterowanie metodzie greet.
Po otrzymaniu od klienta żądania i przyporządkowaniu go do konkretnego kontrolera, serwer rails tworzy instancję klasy danego kontrolera i wywołuje metodę odpowiadającą danej akcji (domyślnie metodę index).
Dodatki do bibliotek Ruby – ActiveSupport
Moduł ActiveSupport zawiera wiele użytecznych rozszerzeń, których można używać pisząc aplikacje Rails:
# generuje format odpowiedni dla bazy danych Time.now.to_s(:db) # => 2007-01-14 23:11:28 session[:remind_me] = 1.week.from_now tags = ["zdjecia", "wakacje", "prywatne"] opis = "Oznaczono jako: " + tags.to_sentence(:connector => 'i', :skip_last_comma => true) # => "Oznaczono jako zdjecia, wakacje i prywatne"
Bazy danych
Rails może współpracować z różnymi odmianami relacyjnych baz danych, jedynym warunkiem jest istnienie odpowiedzialnej za jej obsługę biblioteki dla Ruby oraz obsługa danej bazy przez ActiveRecord – „adaptery” wszystkich popularnych typów baz danych były zawarte w dystrybucji ActiveRecord, jednak począwszy od 2.2 wymagają osobnej instalacji przez RubyGems. W chwili obecnej obsługiwane bazy danych to:
- MySQL
- PostgreSQL
- Oracle
- Microsoft SQL Server
- SQLite (w wersji 2.x i 3.x)
- IBM DB2
- OpenBase
- Sybase
- Firebird[29]
Kod Rails powinien współpracować tak samo ze wszystkimi typami baz danych, pod warunkiem, że programista nie użył jawnie specyficznych dla danej bazy konstrukcji SQL. Rails posiada wbudowany mechanizm „migracji” (ang. migrations), który pozwala tworzyć, zmieniać i kontrolować schemat tabel w bazie danych, niezależnie od jej typu, używając jedynie kodu Ruby.
Jak wspomniano w części Modele – ActiveRecord, Rails może pobierać dane również z plików (w tym XML, YAML, CSV) czy dowolnego innego źródła obsługiwanego przez Ruby.
Bezpieczeństwo
Ruby on Rails oferuje różne wbudowane mechanizmy podnoszące domyślne bezpieczeństwo stworzonej w nim aplikacji. Są to m.in.:
- wartości przed wyświetleniem ich w widoku są automatycznie escape’owane (
<strong>User</strong>
zostanie zamienione na<strong>User<strong>
itp.)[30], - zabezpieczenia przed SQL injection poprzez m.in. używanie placeholderów w zapytaniach,
- zabezpieczenia przed cross-site request forgery (CSRF token)[31],
- zabezpieczenia przed cross-site scripting (XSS),
- opcjonalne szyfrowanie i podpisywanie cookies (domyślne od wersji 4)[32].
Przypisy
- ↑ RailsCarma, The History of Ruby on Rails [online], Medium, 21 września 2015 [dostęp 2021-12-26] (ang.).
- ↑ Rails 1.0: Party like it's one oh oh!.
- ↑ Rails 1.2: REST admiration, HTTP lovefest, and UTF-8 celebrations.
- ↑ Rails 2.0: It's done!.
- ↑ Rails 2.1: Time zones, dirty, caching, gem dependencies, caching, etc.
- ↑ Rails 2.2: i18n, HTTP validators, thread safety, JRuby/1.9 compatibility, docs.
- ↑ Rails 2.3: Templates, Engines, Rack, Metal, much more!.
- ↑ Rails 3.0: It's ready!.
- ↑ Rails 3.1.1 has been released!.
- ↑ Rails 3.2.0: Faster dev mode & routing, explain queries, tagged logger, store.
- ↑ Rails 4.0: Final version released!.
- ↑ Rails 4.1.0: Spring, Variants, Enums, Mailer previews, secrets.yml.
- ↑ Rails 4.2: Active Job, Asynchronous Mails, Adequate Record, Web Console, Foreign Keys. [dostęp 2015-01-23]. (ang.).
- ↑ h, Rails 5.0: Action Cable, API mode, and so much more, „Riding Rails”, 30 czerwca 2016 [dostęp 2017-10-04] (ang.).
- ↑ h, Rails 5.1: Loving JavaScript, System Tests, Encrypted Secrets, and more, „Riding Rails”, 27 kwietnia 2017 [dostęp 2017-10-04] (ang.).
- ↑ h, Rails 5.2.0 FINAL: Active Storage, Redis Cache Store, HTTP/2 Early Hints, CSP, Credentials, „Riding Rails”, 9 kwietnia 2018 [dostęp 2018-06-21] (ang.).
- ↑ h, Rails 6.0: Action Mailbox, Action Text, Multiple DBs, Parallel Testing, Webpacker by default, and Zeitwerk [online], Riding Rails, 15 sierpnia 2019 [dostęp 2019-09-04] (ang.).
- ↑ s (ilustr.), Rails 6.1: Horizontal Sharding, Multi-DB Improvements, Strict Loading, Destroy Associations in Background, Error Objects, and more! [online], Riding Rails, 9 grudnia 2020 [dostęp 2021-03-29] (ang.).
- ↑ Rails 7.0: Fulfilling a vision [online], Ruby on Rails [dostęp 2021-12-27] (ang.).
- ↑ Rails 7.1: Dockerfiles, BYO Authentication, More Async Queries, and more! [online], Ruby on Rails [dostęp 2023-11-02] (ang.).
- ↑ Rails 7.2: Better production defaults, Dev containers, new guides design, and more! [online], Ruby on Rails [dostęp 2024-08-19] (ang.).
- ↑ JustinJ. Weiss JustinJ., A web server vs. an app server [online], Justin Weiss [dostęp 2021-07-10] (ang.).
- ↑ Mongomapper - A Mongo ORM for Ruby
- ↑ Sequel: The Database Toolkit for Ruby
- ↑ DataMapper - Ruby Object Relational Mapper
- ↑ Ruby Object Mapper
- ↑ Dokumentacja Ruby on Rails: ActiveRecord::Timestamps
- ↑ Dokumentacja Ruby on Rails: ActiveRecord::Callbacks
- ↑ The Firebird Adapter now supports Migrations. – cytat za komentarzem w pliku adaptera
- ↑ YehudaY. Katz YehudaY., SafeBuffers and Rails 3.0, „Katz Got Your Tongue”, 1 lutego 2010 [dostęp 2017-10-04] .
- ↑ ActionController::RequestForgeryProtection [online], api.rubyonrails.org [dostęp 2017-10-04] (ang.).
- ↑ ActionDispatch::Session::CookieStore [online], api.rubyonrails.org [dostęp 2017-10-04] (ang.).
Linki zewnętrzne
- Strona domowa Ruby on Rails