Ruby talk romania
-
Upload
koen-handekyn -
Category
Documents
-
view
650 -
download
0
description
Transcript of Ruby talk romania
![Page 1: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/1.jpg)
A Polyglot worldon DSLs
![Page 2: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/2.jpg)
Who Am I
‣ [email protected] UP-nxt, R&D division of the UnifiedPost Group. Electronic Document Handling (Archiving, Legal Delivery, eInvoicing, Payment, Workflow)
‣ Education: Computer Science / Business Administration
‣ Background: Telecommunications
![Page 3: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/3.jpg)
Why Ruby?
PRODUCTIVITY
![Page 4: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/4.jpg)
Why Ruby?
FUN
![Page 5: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/5.jpg)
Why Ruby?
![Page 6: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/6.jpg)
Why is Ruby productive
‣ Simplicity - next time :) ?
‣ Functional Programming - next time :) ?
‣ DSL’s and Meta-Programming
![Page 7: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/7.jpg)
Simplicity
‣ DRY
‣ KISS
‣ YAGNI
‣ Least Surprise
‣ Convention over Configuration (meaningful defaults)
![Page 8: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/8.jpg)
DSL (domain specific languages)
‣ The DSL does not solve every problem in the universe but rather focuses on one little domain • such as building software, querying data, or constructing UIs
‣ Notation conforms to meaning• if you read a sentence (statement) in the DSL, you have a clear, unambiguous idea
of what it does.
‣ A DSL uses high-level concepts that the programmer can use, and translates those to a lower-level implementation (internally).
![Page 9: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/9.jpg)
Internal vs External
‣ An external DSL has it’s own custom scanner and parser or uses a standard one, like XML. example DSL’s : mvn, ANT, SQL, dot, regexp, CSS.
‣ An internal DSL uses a GPL with meta-programming facilities and is hence embedded inside a GPL like Ruby, LISP, Scala. This approach has recently been popularized by the Ruby community. Aka FluentInterfaces
‣ http://martinfowler.com/bliki/DomainSpecificLanguage.html
![Page 10: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/10.jpg)
ActiveAdmin
![Page 11: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/11.jpg)
ActiveAdmin.register Product do
# Create sections on the index screen scope :all, :default => true scope :available scope :drafts
# Filterable attributes on the index screen filter :title filter :author, :as => :select, :collection => lambda{ Product.authors } filter :price filter :created_at
# Customize columns displayed on the index screen in the table index do column :title column "Price", :sortable => :price do |product| number_to_currency product.price end default_actions end
end
![Page 12: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/12.jpg)
ActiveRecord
‣ Properties are dynamically defined. For every column found in the database, a property is added to the class.
‣ Relations also dynamically add methods for working with the corresponding relations in the ER domain
‣ Scopes express named query fragments in an SQL like DSL
class Client < ActiveRecord::Base # the interesting part is ‘the nothing’ has_one :address has_many :orders has_and_belongs_to_many :roles belongs_to :client
scope :published, where(:published => true) scope :published_and_commented, published.and(self.arel_table[:comments_count].gt(0))
end
![Page 13: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/13.jpg)
Example DSL: rake
‣ An ANT like DSL for expressing tasks and task dependencies between them
‣ rake morning:ready_for_the_day• Turned off alarm. Would have liked 5
more minutes, though.• Brushed teeth.• Showered.• Shaved.• Styled hair.• Made 2 cups of coffee. Shakes are gone.• Dog walked.• Ready for the day!
namespace :morning do desc "Turn off alarm." task :turn_off_alarm do puts "Turned off alarm. Would have liked 5 more minutes, though." end
desc "Take care of normal hygiene tasks." task :groom_myself do puts "Brushed teeth." puts "Showered." puts "Shaved." end desc "Make coffee" task :make_coffee do cups = ENV["COFFEE_CUPS"] || 2 puts "Made #{cups} cups of coffee. Shakes are gone." end
desc "Walk the dog" task :walk_dog do puts "Dog walked." end
desc "Get ready for the day" task :ready_for_the_day => [:turn_off_alarm, :groom_myself, ...] do puts "Ready for the day!" endend
![Page 14: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/14.jpg)
Example DSL: rails routes
‣ The Rails router recognizes URLs and dispatches them to a controller’s action. It can also generate paths and URLs, avoiding the need to hardcode strings in your views with shortcuts for REST-full resource
match "/patients/:id" => "patients#show"
resources :photos
namespace :admin do resources :posts, :commentsend
resources :photos
• GET /photos => index• GET /photos/new => new• POST /photos => create• GET /photos/:id => show• GET /photos/:id/edit => edit• POST /photos/:id => update• DELETE /photos/:id => destroy
• photos_path|url => /photos• new_photo_path|url => photos/new• edit_photo_path|url(:id) => photos/:id/edit• photo_path|url(:id) => photos/:id
![Page 15: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/15.jpg)
Capistrino
‣ Capistrano is a utility and framework for executing commands in parallel on multiple remote machines, via SSH.
‣ http://en.wikipedia.org/wiki/Capistrano
task :xml_libs, :hosts => "www.capify.org" do run "ls -x1 /usr/lib | grep -i xml"end
![Page 16: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/16.jpg)
Slop
‣ Slop is a simple option parser with an easy to remember syntax and friendly API.
‣ https://github.com/injekt/slop
opts = Slop.parse do banner "ruby foo.rb [options]\n" on :name=, 'Your name' on :p, :password, 'Your password', :argument => :optional on :v, :verbose, 'Enable verbose mode'end
![Page 17: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/17.jpg)
Workflow
‣ Workflow is a finite-state-machine-inspired API for modeling and interacting with what we tend to refer to as ‘workflow’.
‣ A lot of business modeling tends to involve workflow-like concepts, and the aim of this library is to make the expression of these concepts as clear as possible, using similar terminology as found in state machine theory.
‣ http://www.geekq.net/workflow/
class Article include Workflow workflow do state :new do event :submit, :transitions_to => :awaiting_review end state :awaiting_review do event :review, :transitions_to => :being_reviewed end state :being_reviewed do event :accept, :transitions_to => :accepted event :reject, :transitions_to => :rejected end state :accepted state :rejected endend
![Page 18: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/18.jpg)
Sinatra: A DSL for REST apps
![Page 19: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/19.jpg)
CanCan
‣ CanCan is an authorization library for Ruby on Rails which restricts what resources a given user is allowed to access.
‣ Define abilities• can :manage, Article
‣ Check abilities• cannot? :destroy, @article
• authorize! :read, @article
class Ability
include CanCan::Ability
def initialize(user) if user.admin?
# user can perform any action on any object
can :manage, :all# user can perform any action on the articlecan :manage, Article # negativecannot :destroy, Project # conditionscan :read, Project, :category => { :visible => true }
else # user can read any object
can :read, :all end endend
cannot? :destroy, @articleauthorize! :read, @article
![Page 20: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/20.jpg)
RSpec
‣ RSpec is testing tool for the Ruby programming language. Born under the banner of Behaviour-Driven Development.
require 'bowling'
describe Bowling, "#score" do it "returns 0 for all gutter game" do bowling = Bowling.new 20.times { bowling.hit(0) } bowling.score.should eq(0) endend
describe Order do context "with no items" do it "behaves one way" do # ... end end
context "with one item" do it "behaves another way" do # ... end endend
![Page 21: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/21.jpg)
Cucumber
‣ Cucumber is a tool that executes plain-text functional descriptions as automated tests. The language that Cucumber understands is called Gherkin (external DSL)
‣ Applicable for BDD for Ruby, Java, C#, etc
Feature: Search courses In order to ensure better utilization of courses Potential students should be able to search for courses
Scenario: Search by topic Given there are 240 courses which do not have the topic "biology" And there are 2 courses A001, B205 that each have "biology" as one of the topics When I search for "biology" Then I should see the following courses: | Course code | | A001 | | B205 |
IMPLEMENTING phrases (ruby example)
Given /there are (\d+) coffees left in the machine/ do |n| @machine = Machine.new(n.to_i)end
![Page 22: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/22.jpg)
SLIM
![Page 23: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/23.jpg)
The Future is to the Polyglot
I thank God that I speak in tongues more than all of you (1 Corinthians 14:18)
HTML CSS Javascript
SLIM SASSCoffeescript
JQuery
RubyActiv
eCanC
anWorkflwo
Routes
...
RakeGemfile
Puppet
RSpec
Cucumber
...
SQL REDIS MongoDB
Client
Client Source
Server(Business
Layer)
PersistenceLayer
Infrastructure
![Page 24: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/24.jpg)
DSL toolbox
META-PROGRAMMING
*code* that generates *code*
![Page 25: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/25.jpg)
But beware
![Page 26: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/26.jpg)
But beware
![Page 27: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/27.jpg)
Swords, Guns, and other toys
‣ symbols. These have less line-noise than strings and tend to be favored by DSL writers.‣ procs. More than anything else, these make DSL’s in Ruby read and work naturally. They
allow simple encapsulation of functionality (so you can write augmented branching constructs), and also let you do delayed evaluation of code.
‣ modules. With modules you can easily specialize individual objects with DSL methods.‣ eval, instance_eval, and class_eval. It is definitely worth learning the difference
between these three, and how they can be used. These are critical to many different dynamic techniques.
‣ define_method. This lets you define new methods that can reference their closure, which you can’t do so easily using the eval methods.
‣ alias_method. Rails uses this to good effect to allow modules to override behavior of the classes they are included in.
‣ Module#included lets you do additional processing at the moment that a module is included in a class.
‣ Class#inherited lets you keep track of who is inheriting from what
![Page 28: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/28.jpg)
Properties :)
‣ monkey patch Object
‣ yield self from constructor
class Developer properties :level, :name, :surname
def initialize yield ( self ) if block_given? endend
# Test our Setterssuperduperdev = Developer.new do |d| d.level = "journeyman" d.name = "Edmore" d.surname = "Moyo"end
anotherdev = Developer.new(name: "koen", surname: "handekyn", level: "ceo")
class << Objectdef property( *names )
" names.each do |name|" define_method( "#{name}=" ) do |value|" instance_variable_set( "@#{name}", value )" end define_method( name ) do" eval("@#{name}") end end end alias_method :properties, :property" end
![Page 29: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/29.jpg)
Class Macro
class << Object def macro(args) puts args endend
class C macro :testend
![Page 30: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/30.jpg)
Hooks
$INHERITORS = []
class Animal def self.inherited(subclass) $INHERITORS << subclass endend
class Fish < Animal def a() endendclass Dog < Animal def b() endendclass Cat < Animal def c() endend
puts $INHERITORS.map { |c| c.name }.sort
# Cat# Dog# Fish
![Page 31: Ruby talk romania](https://reader033.fdocuments.in/reader033/viewer/2022060110/555ada5fd8b42a024a8b4f01/html5/thumbnails/31.jpg)
Q&A