jarorcon sp

33
Mirosław Wołoszyn Przemysław Kowalczyk Jarorcon Sp. z o.o. ul. Wałbrzyska 12 52-314 Wrocław email: [email protected]

Upload: jarorcon

Post on 18-May-2015

1.680 views

Category:

Technology


0 download

DESCRIPTION

Jarorcon company introducing Ruby on Rails

TRANSCRIPT

Page 1: Jarorcon Sp

Mirosław WołoszynPrzemysław Kowalczyk

Jarorcon Sp. z o.o.

ul. Wałbrzyska 12

52-314 Wrocław

email: [email protected]

Page 2: Jarorcon Sp

www.susuh.de

Użyte technologie: Ruby on Rails, Ajax, JavaScrip, XML, MySql, Apache, Mongrel, Memcache, Ferret, GetText, RCov, Test Driven Development Serwisy zintegrowane z portalem: Jajah, Twistage, Sevenload, HiClip, Google Maps Api, Ad Sense, Octazen Invite Sender & Contact Importer

Runek usług Susuh.

Page 3: Jarorcon Sp

www.define-finance.com

Użyte technologie: Ruby on Rails, Behaviour Driven Development (RSpec), Ajax, Javascript, XML, MySql, Apache, Mongrel, Memcache, Ferret, GetText, BackgrounDRb Serwisy zintegrowane z portalem: Sevenload

Portal dla osób działających na europejskim rynku finansów i ubezpieczeń.

Page 4: Jarorcon Sp

www.absolventa.de

Portal pracy przeznaczony dla absolwentów.

Użyte technologie: Ruby on Rails, Behaviour Driven Development (RSpec), Ajax, Javascript, XML, MySql, Apache, Mongrel, Memcache, BackgrounDRb Serwisy zintegrowane z portalem: Amazon S3

Page 5: Jarorcon Sp

Praca, praktyka w Jarorcon Sp. z o.o.

Wrocław - praca we Wrocławskim biurze firmy Jarorcon Sp. z o.o.

Hamburg - praca w niemieckiej firmie AKRA GmbH.

Kontakt: [email protected] www.jarorcon.pl

Page 6: Jarorcon Sp

Rubyi

Rails

Przemysław Kowalczyk

Jarorcon sp. z o.o.

Page 7: Jarorcon Sp

O mnie

Absolwent Uniwersytetu Wr., 1999 r., kierunek: Informatyka, specjalizacja: Inżynieria Oprogramowania

Pracuję jako programista od 1997 r. Java: 6 lat,

C++: 4 lata, Ruby: prawie rok

Aplikacje WWW: prawie 7 lat

Page 8: Jarorcon Sp

Plan prezentacji

Ruby Ruby <=> Java przykłady

Ruby on Rails wprowadzenie przykłady

ActiveRecord ActiveRecord <=> JPA przykłady

Page 9: Jarorcon Sp

Stworzony w 1995 r. przez Yukihiro Matsumoto (a.k.a. "Matz")

“Designed for programmer productivity and fun!”

Page 10: Jarorcon Sp

Ogólnego zastosowania

Wieloplatformowy Open source Obiektowy Elastyczny

Automatyczne zarządzanie pamięcią

Refleksja Inspiracje:

Smalltalk Perl Lisp Python

Page 11: Jarorcon Sp

Ruby <=> Java

Kompilowany Statyczne typowanie

Wszystko jest obiektem

(oprócz typów prymitywnych, tablic, interfejsów, enumów, adnotacji) ☺

Wywoływanie metod

Interpretowany Dynamiczne typowanie

(duck-typing) Wszystko jest obiektem

(klasy, moduły)

Wysyłanie komunikatów

Page 12: Jarorcon Sp

Ruby <=> Java Ruby > Java

Zwięzły, wyrazisty kod => szybsze tworzenie, niższe koszty utrzymania

DSL (Domain Specific Language) => myślenie pojęciami z dziedziny problemu

Otwarte klasy, metaprogramowanie => łatwość tworzenia DSL, frameworków, AOP (programowanie aspektowe)

Przyjazny dla programisty: składnia, Principle of Least Surprise

Ruby < Java Wolniejszy (ale: JRuby, wiele innych implementacji w toku)

Słabe wsparcie Unicode (tylko UTF-8, poprawione w Ruby 1.9)

Trudniejszy refactoring

Bardziej wymagający (łatwiej sobie zrobić krzywdę)

Page 13: Jarorcon Sp

Przyjazna składnia

puts 'Hello World!'

10.times {puts 'Hello'}

array = [1, 'hi', 3.14, 1, 2, [4, 5]]

hash = {'water' => 'wet', 'fire' => 'hot'}puts hash['water']

Nawiasy opcjonalne

int też obiekt i swoje metody ma

Składnia dla tworzenia tablic

Składnia dla tworzenia tablic asocjacyjnych

Metody mogą mieć blok kodu jako parametr

Średniki opcjonalne

Page 14: Jarorcon Sp

Przyjazna składnia

def fib n return 1 if n < 2 fib(n-1) + fib(n-2)end

n = 5

puts "#{n}-th Fibonacci number is #{fib n}"

(1..10).map {|i| i * 2}.find_all {|i| i%3 == 0}

=> [6, 12, 18]

Skrócona forma if

return zbędny na końcu metody

Interpretowane wewnątrz napisu

Tworzy obiekt klasy Range

Page 15: Jarorcon Sp

Zwięzły kod

top5 = users. sort_by{|u| u.activity}. last(5). collect{|u| u.login}

Collections.sort(users, new Comparator<User>() {

public int compare(User u1, User u2) {

return u1.getActivity() - u2.getActivity();

}

});

List<String> top5 = new ArrayList<String>(5);

for (User user : users.subList(users.size() - 5, users.size())) {

top5.add(user.getLogin());

}

Dostępne w Rails i Ruby 1.9

top5 = users. sort_by(&:activity). last(5). collect(&:login)

Podejrzane!

Błędy!

Accidentalcomplexity!

Page 16: Jarorcon Sp

DSL – Domain Specific Language

class User < ActiveRecord::Base

has_many :projects

belongs_to :department

validates_presence_of :name

validates_uniqueness_of :login

validate :blacklisted_login?

before_save :encrypt_password

...

Page 17: Jarorcon Sp

Otwarte klasy

class String def blank? self.strip == '' endend

class NilClass def blank?; true; endend

"RUBY".length

"RUBY".blank?

nil.blank?

public class StringUtils { public static boolean isBlank(String str) { return str == null || str.trim().equals(""); }}

"JAVA".length();

StringUtils.isBlank("JAVA");

StringUtils.isBlank(null);

Osobna klasa!Metoda statyczna!

Brak konsekwencji!

Page 18: Jarorcon Sp

Metaprogramowanie

xml = XmlGenerator.new

puts xml.people {

xml.person {

xml.name {"Gallagher"} +

xml.profession {"inventor"} +

xml.fictional

}

}

<people><person><name>Gallegher</name><profession>inventor</profession><fictional/></person></people>

class XmlGenerator

def method_missing m, *args

if block_given?

"<#{m}>#{yield}</#{m}>"

else

"<#{m}/>"

end

end

end

Page 19: Jarorcon Sp

Metaprogramowanie

Person = Struct.new(:name, :phone, :email)p1 = Person.new(:name => "DHH")

#Campingclass Post < R '/post/(\d+)' def get post_id ... endend

def run_tests methods.grep /^test_/ do |m| self.send m endend

Page 20: Jarorcon Sp

Ruby on Rails

Twórca: David Heinemeier Hansson Data opublikowania: lipiec 2004 r. Obecna wersja stabilna: 2.0.2 Stworzony przez

wydzielenie z istniejącejaplikacji (Basecamp)

Page 21: Jarorcon Sp

Ruby on Rails – buzzwords

MVCAJAXRESTDRYConvention over Configuration

Generatory plikówplugins wsparcie dla TDD

Web development that doesn't hurt!

Optimized for programmer happiness

Does it scale?YES!

Ruby will reach 4 million programmers by 2013 (Gartner)

Page 22: Jarorcon Sp

Ruby on Rails – enterprise ready?

amazon.com BBC CapGemini Cisco C|Net EA (Electronic Arts) IBM JP Morgan NASA Oracle

New York Times NBC Barclays LA Times Chicago Tribune Orbitz Google Turner Media Siemens Yahoo!

YES!

Page 23: Jarorcon Sp

Convention over Configuration

MessageFoldersController(klasa kontrolera)

message_folders(tabela)

MessageFolder(klasa modelu)

app/models/message_folder.rb(plik)

MessageFolderTest(klasa testowa dla modelu)

test/unit/message_folder_test.rb(plik)

app/controllers/message_folders_controller.rb(plik)

app/views/message_folders/index.rhtmledit.rhtml

show.rhtml(widoki)

MessageFoldersControllerTest(klasa testowa dla kontrolera)

test/functional/message_folders_controller_test.rb(plik)

Page 24: Jarorcon Sp

Ruby on Rails – model

class Campaign < ActiveRecord::Base

has_many :codes, :dependent => :destroy has_many :free_codes, :class_name => "Code", :conditions => "user_id is null" belongs_to :creator, :class_name => "User"

validates_presence_of :name, :valid_from, :valid_to, :invitations_no validates_uniqueness_of :name

def initialize *args super if @new_record valid_from ||= Time.now.tomorrow.midnight valid_to ||= 2.weeks.since(valid_from) invitations_no ||= 5 end end

def active? Time.now >= valid_from && Time.now <= valid_to endend

Operacje na czasie i datach

Nazwa klasy na podstawie nazwy relacji

Page 25: Jarorcon Sp

Ruby on Rails – controller

class AdminCampaignsController < ApplicationController before_filter :admin_required caches_page :index, :show cache_sweeper :campaign_sweeper, :only => [:create, :update, :destroy]

def index @campaigns = Campaign.paginate :all, :page=>params[:page], :per_page=>25 end

def edit @campaign = Campaign.find(params[:id]) end

def update @campaign = Campaign.find(params[:id]) if @campaign.update_attributes(params[:campaign]) flash[:notice] = _('Campaign was successfully updated.') redirect_to admin_campaign_url(@campaign) else render :action => "edit" end end

...

Cache'owanie!

Page 26: Jarorcon Sp

Ruby on Rails – view

<h1>New campaign</h1><%= error_messages_for :campaign %><% form_for(:campaign, :url => admin_campaigns_path) do |f| %> <%= render :partial => 'form', :locals => { :f => f } %> <p> <%= submit_tag "Create" %> </p><% end %><%= link_to 'Back', admin_campaigns_path %>

<p> <b>Name</b><br /> <%= f.text_field :name %></p>

<p> <b>Valid from</b><br /><%= f.datetime_select :valid_from %></p>

<p> <b>Valid to</b><br /> <%= f.datetime_select :valid_to %></p>

Formularz dla modelu

Wstawienie fragmentu strony

Partial '_form.rhtml'

Widok 'new.rhtml'

Page 27: Jarorcon Sp

Ruby on Rails – test

class AdminCampaignsControllerTest < Test::Unit::TestCase

fixtures :campaigns, :campaign_codes

def test_should_get_index get :index assert_response :success assert assigns(:campaigns) end

def test_should_create_campaign assert_difference Campaign, :count, 1 do post :create, :campaign => { :name => 'test campaign' } end

assert_redirected_to admin_campaign_path(assigns(:campaign)) end

def test_shouldnt_create_campaign_without_name assert_difference Campaign, :count, 0 do post :create, :campaign => { :name => '' } end assert_not_nil assigns(:campaign).errors.on(:name) end

Fixtures – predefiniowane dane w bazie testowej

Wykonanie żądania HTTP: GET index

Blok kodu powinien zwiększyć Campaign.count o 1

Wykonanie żądania HTTP: POST create z parametrami

Page 28: Jarorcon Sp

ActiveRecord <=> JPA

Wzorzec projektowy: ActiveRecord

Atrybuty zdefiniowane w tabeli

Relacje zdefiniowane w klasie

Mapowanie automatyczne

Finders, dynamic finders, SQL

Wzorzec projektowy: DataMapper

Atrybuty zdefiniowane w klasie

Relacje zdefiniowane w klasie lub XML

Mapowanie przez adnotacje lub XML

Criteria, HQL, SQL

Page 29: Jarorcon Sp

ActiveRecord

find(:first, :conditions => [ "user_name = ? AND password = ?", user_name, password ])

find(:first, :conditions => { :user_name => user_name, :password => password })

find(:first, :conditions => params[:user])

find_by_user_name_and_password(user_name, password)

Tag.find_or_create_by_name("Summer")

user.manager.projects.find(project_id)

manager.projects.create(:name => 'new project')

Dynamic finder

Znajdź lub stwórz

User belongs_to :manager

Manager has_many :projects

Znajduje projekt, ale tylko wtedy, gdy ma go manager danego użytkownika

Page 30: Jarorcon Sp

ActiveRecord (2)

Person.find(:all, :include => [ :account, :friends ])

Company.find(:first, :conditions => [ "id = :id AND name = :name AND division = :division AND created_at > :accounting_date", { :id => 3, :name => "37signals", :division => "First", :accounting_date => '2005-01-01' }]

Message.find(all, :select => "messages.*", :joins => "INNER JOIN message_folder_items mfi ON (mfi.message_id = messages.id)", :conditions => ["mfi.message_folder_id = ?", self.id], :order => 'messages.sent_at desc', :limit => 20)

Eager loading

Page 31: Jarorcon Sp

YAML <=> XML

dates:

month names: [sty, lut, mar, kwi, ...]

day names: [Nie, Pon, Wto, Śro, ...]

date formats:

short: '%e %b'

long: '%e %B %Y'

numbers:

separator: '.'

delimiter: ','

precision: 3

<format> <dates> <month-names> <month-name>sty</month-name> <month-name>lut</month-name> <month-name>mar</month-name> <month-name>kwi</month-name> <month-name>...</month-name> </month-names> <day-names> <day-name>Nie</day-name> <day-name>Pon</day-name> <day-name>Wto</day-name> <day-name>Śro</day-name> <day-name>...</day-name> </day-names> <date-formats> <short>%e %b</short> <long>%e %B %Y</long> </date-formats> </dates> <numbers> <separator>.</separator> <delimiter>,</delimiter> <precision>3</precision> </numbers></format>

Page 32: Jarorcon Sp

Przydatne adresy

http://www.ruby-lang.org/pl/ http://www.rubyonrails.org/ http://jarorcon.pl/ http://szeryf.wordpress.com/

Page 33: Jarorcon Sp

Pytania?