14. Dedenie
class Instrument
def tune
...
end
end
class Violin < Instrument
def play
tune
"Taa daa"
end
end
15. Overloading v ruby nefunguje
class Instrument
def play
"Ta da"
end
def play(octave)
"Ta da #{octave}"
end
end
i = Instrument.new
i.play #=> ArgumentError: wrong number of arguments (0 for 1)
i.play('c dur') #=> "Ta da c dur"
16. Overriding
class Instrument
def play
"Ta da"
end
end
class Violin < Instrument
def play
"Tiii diii tiii"
end
end
v = Violin.new
v.play #=> "Tiii diii tiii"
17. Polymorfia
class Instrument
def play
end
end
class Violin < Instrument
def play
"Taa daa"
end
end
class Drum < Instrument
def play
"Dum dum"
end
end
orchestra = [Violin.new, Violin.new, Drum.new]
orchestra.each { |i| i.play }
#=> "Taa daa", "Taa daa", "Dum dum"
20. ActiveSupport try
p = Person.find(params[:id])
p.address.downcase
#=> NoMethodError: undefined method `downcase'
# for nil:NilClass
p.address.try :downcase #=> nil
21. Aj metóda
class Person
def greet(other_person)
"Ahoj #{other_person}"
end
end
m = Person.instance_method(:greet)
m.class #=> UnboundMethod
m.arity #=> 1
m.name #=> :greet
m.parameters #=> [[:req, :other_person]]
24. Modul ako namespace
module Rubyslava
class OOP
end
end
module Pyvo
class OOP
end
end
Rubyslava::OOP == Pyvo::OOP #=> false
25. Modul ako nositeľ kódu
module Rubyslava
def hello
"Rubyslava"
end
end
26. Mixiny
class RubyslavaAPyvo
include Rubyslava
end
rp = RubyslavaAPyvo.new
rp.hello #=> "Rubyslava"
class RubyslavaAPyvo
extend Rubyslava
end
RubyslavaAPyvo.hello #=> "Rubyslava"
27. Viacnásobné dedenie
class RubyslavaAPyvo < Array
include Rubyslava, Pyvo
end
RubyslavaAPyvo.ancestors
#=> [RubyslavaAPyvo, Rubyslava, Pyvo
# Array, Object, Kernel, BasicObject]
29. module AdditionalBehaviour
def show
greet
end
end
class Test
include AdditionalBehaviour
def greet
"hello"
end
end
Test.new.show #=> "hello"
30. module GreetingBehavior
def greet
"hello"
end
end
module RelyOnGreetingBehavior
def show
greet
end
end
class Test
include GreetingBehavior, RelyOnGreetingBehavior
end
Test.new.show #=> "hello"
31. Zo života
Enumerable
acts_as_..
ActiveSupport::Concern
32. class Tree
include Enumerable
def each(&block)
leafs.each do { |n| yield n }
end
end
t = Tree.new
t.map
t.inject
t.sum
...
33. class Post
acts_as_taggable
end
p = Post.find(1)
p.tag_list #=> ["Ruby", "OOP"]
34. ActiveSupport::Concern
module Annotatable
extend ActiveSupport::Concern
included do
has_many :notes, :as => :annotatable,
:order => "created_at DESC"
end
def most_annotated
joins(:notes).group(:id).order("COUNT(*) DESC").first
end
end
class Project < ActiveRecord::Base
include Annotatable, Importable, Versionable
end
42. Singleton
class Logger
def initialize
@log = File.open("log.txt", "a")
end
@@instance = Logger.new
def self.instance
@@instance
end
def log(msg)
@log.puts(msg)
end
private_class_method :new
end
Logger.instance.log('message 1')
43. Singleton (lepšie)
require 'singleton'
class Logger
include Singleton
def initialize
@log = File.open("log.txt", "a")
end
def log(msg)
@log.puts(msg)
end
end
Logger.instance.log('message 2')
50. Delegator
include 'forwardable'
class Car
extend Forwardable
def_delegators :@car_computer, :velocity,
:distance
def initialize
@car_computer = CarComputer.new
end
end
c = Car.new
c.velocity
c.distance
52. Proxy
require 'delegate'
class Future < SimpleDelegator
def initialize(&block)
@_thread = Thread.start(&block)
end
def __getobj__
__setobj__(@_thread.value) if @_thread.alive?
super
end
end
google = Future.new do
Net::HTTP.get_response(URI('http://www.google.com')).body
end
yahoo = Future.new do
Net::HTTP.get_response(URI('http://www.yahoo.com')).body
end
puts google
puts yahoo
55. class Game
def play
prepare_board
initialize_score
while not end_of_game?
make_move
end
end
end
class Carcassonne < Game
def make_move
tile = tiles.pick_random
...
end
end
class Agricola < Game
def make_move
peasant = select_peasant
...
end
end
57. class Person
def say
"#{@name}"
end
end
class Family
attr_accessor :members
def initialize(members)
@members = members
end
def say
@members.each { |m| m.say }
end
end
f = Family.new(Person.new('Janko'), Person.new('Tomas'))
t = Family.new(Person.new('Ferko'), f)
t.say #=> "Ferko", "Janko", "Tomas"
59. class FileLogger < Logger
def log(message)
File.open('a') { |f| f << message }
end
end
class DatabaseLogger < Logger
def log(message)
Log.create(:message => message)
end
end
61. class TrafficLight
include AlterEgo
state :proceed, :default => true do
handle :color do
"green"
end
transition :to => :caution, :on => :cycle!
end
state :caution do
handle :color do
"yellow"
end
transition :to => :stop, :on => :cycle!
end
state :stop do
handle :color do
"red"
end
transition :to => :proceed, :on => :cycle!
end
end
64. class Comment < ActiveRecord::Base
end
class CommentObserver < ActiveRecord::Observer
def after_save(comment)
Notifications.deliver_comment("admin@do.com",
"New comment was posted", comment)
end
end
67. class Container
def add(node)
if node.kind_of? Array
node.each { |n| @nodes << n }
else
@nodes << node
end
end
end
container.add(Tree.new('a', 'b')) #=> ???
68. class Container
def add(node)
unless node.respond_to? :each
node = [node]
end
node.each { |n| @nodes << n }
end
end
container.add(Tree.new('a', 'b')) #=> ['a', 'b']
69. Protipríklad
ActiveRecord::sanitize_sql_for_assignment
def sanitize_sql_for_assignment(assignments)
case assignments
when Array
sanitize_sql_array(assignments)
when Hash
sanitize_sql_hash_for_assignment(assignments)
else assignments
end
end
70. Visitor + typy
def visit object
method = "visit_#{object.class.name}"
send method, object
end
module Arel
module Visitors
class WhereSql < Arel::Visitors::ToSql
def visit_Arel_Nodes_SelectCore o
"WHERE #{o.wheres.map { |x| visit x }.join ' AND ' }"
end
end
end
end
71. Shotgun surgery
ak niečo mením tak musím na viacerých
miestach
crosscutting concerns
AOP (AspectJ)
75. Autorizácia
class DocumentController < ApplicationController
before_filter :find_document
def show
# render @document
end
private
def find_document
@document = Document.find_by_id(params[:id])
end
end
76. class DocumentController < ApplicationController
before_filter :find_document
around_filer :authorize
def show
# render @document
end
private
def find_document
@document = Document.find_by_id(params[:id])
end
def authorize
if current_user.can_view?(@document)
yield
else
render :not_authorized
end
end
end
87. Dátová trieda
class SubjectController < ApplicationController
def show
if @subject.updated_at < Time.now - 2.weeks.ago
@subject.refresh
end
end
end
class Subject < ActiveRecord::Base
end
88. Dátová trieda 2
class SubjectController < ApplicationController
def show
@subject.update_if_stale
end
end
class Subject < ActiveRecord::Base
def update_if_stale
refresh if updated_at < Time.now - 2.weeks.ago
end
end
class Person < Subject
def update_if_stale
# update vsetky firmy kde je subjekt
end
end
89. Komentáre
# download new version of article
def perform(x)
# load article from the url 'x'
...
end
def download_article(url)
...
end