Matti Paksula / Syksy 2009
Tietojenkäsittelytieteen laitos
Helsingin Yliopisto
Kurssista on mahdollista saada 4op + 1op tekemällä "27h" enemmän töitä.
Kurssin jälkeen on mahdollista työllistyä Rails-kehittäjänä
"Rails isn't playing catch-up with the new de facto web standards; it's helping define them."
taulukko = ["ruby", "python", "perl", "php"] if taulukko.include? "php" puts "Voi ei, otetaan PHP pois" taulukko.delete "php" end unless taulukko.include? "scala" puts "Scala puuttuu!" taulukko << "scala" end class Koe def metodi puts("sulkuja") ; puts("ja puolipilkkujakin!") end end kokeilu = Koe.new kokeilu.metodi 10.times { puts "Mahtava kieli!" }
"Agility is part of the fabric of Rails"
-pr
" (pure ruby) -versioita, jotka eivät sisällä natiivikoodia ja ovat täten hitaita
Varsinaisesta IDE:stä ei välttämättä ole hyötyä, hyvä tekstieditori toimii paremmin.
Laitokselle asennettu valmiiksi "hyvät oletukset"
rails applikaation_nimi
.
|-- README Geneerinen readme
|-- Rakefile "rake" -komennon oletus "Makefile"
|-- app Koko applikaation koodi tulee pääosin tänne
| |-- controllers Kaikki controllerit, elikkäs ohjaimet
| | `-- application_controller.rb Yläluokka kaikille controllereille, oletusarvoisesti kaikki periytyvät tästä
| |-- helpers Viewien apumetodit
| | `-- application_helper.rb Yläluokka helppereille
| |-- models Modelit, eli tietokantatauluja edustavat luokat
| `-- views Näkymät
| `-- layouts Näkymäwrapperit
|-- config Konfiguraatiotiedostot
| |-- boot.rb Railssin alustus
| |-- database.yml Tietokantakonfiguraatiot YAML -muodossa
| |-- environment.rb Koko applikaatiota koskevat ympäristöasetukset.
| |-- environments Eri ympäristöjen asetukset
| | |-- development.rb Kehitysympäristö
| | |-- production.rb Tuotantoympäristö
| | `-- test.rb Testausympäristö
| |-- initializers Lisää asetuksia, ajetaan kerran käynnistyksessä
| | |-- backtrace_silencers.rb kts. sisältö
| | |-- inflections.rb Sanojen taivutuksen määrittely, tarvitaan tietokantataulujen nimeämiseen.
| | |-- mime_types.rb Tuetut mime-tyypit
| | |-- new_rails_defaults.rb Rails 2.0 -> 3.0 -asioita
| | `-- session_store.rb Määrittelee missä sessiot säilytetään, oletusarvoisesti cookiessa.
| |-- locales Lokalisointi
| | `-- en.yml Kielen lokalisointitiedosto
| `-- routes.rb Määrittelee miten URL:t yhdistyvät applikaation controllereihin.
|-- db Tietokantaskeemat, SQLite -kannan oletussijainti
|-- doc Dokumentaatio tänne..
| `-- README_FOR_APP ..ehkä
|-- lib Applikaation käyttämät kirjastot, katso myös "vendor"
| `-- tasks Applikaation Rake -taskit
|-- log Eri ympäristöjen logitiedostot
| |-- development.log
| |-- production.log
| |-- server.log
| `-- test.log
|-- public Applikaation staattiset tiedostot
| |-- 404.html Oletusarvoinen 404, annetaan myös silloin kun haettua tietoa ei löydy tietokannasta
| |-- 422.html Access denied
| |-- 500.html Näytetään, kun applikaatio suorittaa poikkeuksen
| |-- favicon.ico
| |-- images Kuvat tänne
| | `-- rails.png ..
| |-- index.html Tämä pitää poistaa, jotta "/" -URL toimii
| |-- javascripts JavaScriptit
| | |-- application.js Applikaation omat JavaScriptit tänne
| | |-- controls.js script.aculo.us -kirjaston muinainen versio
| | |-- dragdrop.js ..drag'n'drop -kirjasto
| | |-- effects.js ..ja effect. Nämä voi halutessaan poistaa tai päivittää uudempiin.
| | `-- prototype.js Prototype JavaScript -kirjasto
| |-- robots.txt robots.txt
| `-- stylesheets Tyylitiedostot tänne
|-- script Railssin omat skriptit
| |-- about Kertoo tietoja ajoympäristöstä
| |-- console irb konsoli Rails-tuella
| |-- dbconsole Valitun tietokannan konsoli
| |-- destroy Poistaa generoituja tiedostoja
| |-- generate Generoi tiedostoja
| |-- performance Suorituskykytestausta
| | |-- benchmarker
| | `-- profiler
| |-- plugin Asentaa plugineja vendor/plugins
-kansioon
| |-- runner Suorittaa mitä tahansa koodia
| `-- server Käynnistää paikallisen web-serverin (Webrick tai Mongrel)
|-- test Test::Unit -yksikkötestit
| |-- fixtures Valmis tietosisältö testeihin (tai kehitykseen)
| |-- functional
| |-- integration
| |-- performance
| | `-- browsing_test.rb
| |-- test_helper.rb
| `-- unit Yksikkötestit modeleille
|-- tmp Väliaikaistiedostot
| |-- cache
| |-- pids
| |-- sessions
| `-- sockets
`-- vendor
`-- plugins Pluginit
app/models
script/generate model Course name:string
db/migrate/timestamp_create_courses.rb
rake db:migrate
c = Course.new c.name = "Ruby on Rails" c.description = "Syksyn ketterin kurssi" c.save
app/controllers
script/generate controller Courses index
config/routes.rb
määritellään miten URL:t ohjautuvat millekkin controllerillemap.connect ':controller/:action/:id'
määrittelee mm. seuraavat URL:t
routes.rb
tiedostoa päivitetään, tulee käynnistää palvelin uudestaanscript/server
http://localhost:3000/courses/index
def index @courses = Course.find(:all) end
@courses
-instanssin näkymälle<h1>Ilmo 2.0</h1> <% @courses.each do |course| %> <%= course.name %><br/> <% end %>
RAILS_ENV
-ympäristömuuttuja määrittelee missä ympäristössä toimintaandevelopment
-ympäristössäproduction
-ympäristössä ei ladata luokkia uudestaan jokaiselle requestille ym.production
-ympäristössä.Perjantai 10-12
# Leikkikää irb:ssä! hajautustaulu = {} hajautustaulu = Hash.new hajautustaulu[:avain] = "symboli -avaimen arvo" hajautustaulu["avain"] = "string -avaimen arvo" hajautustaulu[23] = "integer -avaimen arvo" # >> hajautustaulu # => { :avain=>"symboli -avaimen arvo", # 23=>"integer -avaimen arvo", # "avain"=>"string -avaimen arvo"}
# id:n perusteella Course.find(1) # nimen perusteella Course.find_by_name("rio") # useamman kentän perusteella Course.find_by_name_and_description("rio", "rinnakkaisohjelmointi")
c = Course.new :name => "LaMa" c = Course.new({:name => "LaMa"}) c.save
c = Course.find(:first) c = Course.first c.name = c.name.upcase c.save
Course.destroy(1) c = Course.last c.destroy Course.destroy_all :name => "Rails"
Course.count Person.count(:conditions => "age > 26 \ AND salary > 60000")
rake db:seed & db/seed.rb
ARGV
-taulukkolink_to
params
-muuttujalayouts
yield
(kiinnostuneille)helpers
& tehdään oma link_to
-toteutusroutes.rb
& named routes
rake routes
-komentoredirect_to
log/
-hakemistoadd_column
& rename_column
Flash
-viestit näkymissäform_for
# Original controller code def authenticate if params[:login][:username] and params[:login][:password] user = User.authenticate(params[:login][:username], params[:login][:password]) if user # password correct session[:user] = user redirect_to_stored else # password wrong redirect_to :action=>"index" end end end # Better implementation def authenticate # No need to check if params were given to controller # if params[:login][:username] and params[:login][:password] user = User.authenticate(params[:login][:username], params[:login][:password]) if user # 1) Don't store entire user object in session # 2) Wrap a method around login, so that we can change authentication behaviour if needed # session[:user] = user login_user(user) redirect_to_stored # This probably was to redirect to "attempted page" (before filter) so this might be okay! else # If we change our page to use for login, let's use a named_route for that # redirect_to :action=>"index" redirect_to login_page end end # refactored def authenticate user = User.authenticate(params[:login][:username], params[:login][:password]) if user login_user(user) redirect_to_stored # This probably was to redirect to "attempted page" (before filter) so this is okay. else redirect_to login_page end end # Original controller code def logout Offer.unlock_all_by_user_id(session[:user].id) if session[:user] session[:user] = nil redirect_to :controller=>"offer", :action=>"index" end # Better implementation def logout # Wrap this to logout(user) or user.logout! -method # Note also that I checked if session[:user] exists even if we are in logout, where it exists. # Offer.unlock_all_by_user_id(session[:user].id) if session[:user] Offer.unlock_by(user) # Unlock all by user user.logout! # Logout user # As above, use named routes to ensure readability #redirect_to :controller=>"offer", :action=>"index" redirect_to root_url end # refactored def logout Offer.unlock_by(user) user.logout! redirect_to root_url end # original controller code if not @offer.locked.nil? and @offer.locked != session[:user].id redirect_to :action=>"edit_lock", :id=>@offer.id else @offer.lock = session[:user].id end # step 1 # 1) use implement locking check at instance # 2) use current_user instead of session if @offer.locked? and @offer.locked != current_user.id redirect_to :action=>"edit_lock", :id=>@offer.id else @offer.lock = current_user.id end # step 2 # 1) combine lock checking with user at instance if @offer.locked_by?(current_user) # use resources instead of direct classes and actions redirect_to edit_offer_lock(@offer) else # Implement locking at lower level, this implementation can be changed without breaking API to controllers @offer.lock_for(current_user) end # refactored: if @offer.locked_by?(current_user) redirect_to edit_offer_lock(@offer) else @offer.lock_for(current_user) end
named_scope :by_popularity, :order => "(SELECT count(*) from registrations r left join exercise_groups eg on eg.id = r.exercise_group_id left join course_instances ci on ci.id = eg.course_instance_id where ci.course_id = courses.id group by ci.course_id) DESC"