D-Talk: What's awesome about Ruby 2.x and Rails 4

67
RUBY 2.X Thursday, October 10, 13

description

D-Talk by Jan Berdajs

Transcript of D-Talk: What's awesome about Ruby 2.x and Rails 4

Page 1: D-Talk: What's awesome about Ruby 2.x and Rails 4

RUBY 2.X

Thursday, October 10, 13

Page 2: D-Talk: What's awesome about Ruby 2.x and Rails 4

2012Thursday, October 10, 13

Page 3: D-Talk: What's awesome about Ruby 2.x and Rails 4

RUBY

+ berljivost+ površinska enostavnost+ polno objektni jezik+ funkcijsko programiranje+ metaprogramiranje+ ekosistem+ RubyGems

- metaprogramiranje- hitrost vs. Scala, Java, C- znanost (SciPy)

Thursday, October 10, 13

Page 4: D-Talk: What's awesome about Ruby 2.x and Rails 4

(0..10).each do |x| puts "The number is: #{x}"end

<?php for ($x=0; $x<=10; $x++){ echo "The number is: $x";}?>

for x in range(0, 11): print 'The number is: %d' % (x)

Ruby PHP Python

Thursday, October 10, 13

Page 5: D-Talk: What's awesome about Ruby 2.x and Rails 4

(0..10).each do |x| puts "The number is: #{x}"end

<?php for ($x=0; $x<=10; $x++){ echo "The number is: $x";}?>

for x in range(0, 11): print 'The number is: %d' % (x)

Ruby PHP Python

for x in 0..10 puts 'The number is: %d' % [x]end

Thursday, October 10, 13

Page 6: D-Talk: What's awesome about Ruby 2.x and Rails 4

(0..10).each do |x| puts "The number is: #{x}"end

<?php for ($x=0; $x<=10; $x++){ echo "The number is: $x";}?>

for x in range(0, 11): print 'The number is: %d' % (x)

Ruby PHP Python

for x in 0..10 puts 'The number is: %d' % [x]end

0.upto(10).each { |x| printf('The number is: %d', x)}

Thursday, October 10, 13

Page 7: D-Talk: What's awesome about Ruby 2.x and Rails 4

(0..10).each do |x| puts "The number is: #{x}"end

<?php for ($x=0; $x<=10; $x++){ echo "The number is: $x";}?>

for x in range(0, 11): print 'The number is: %d' % (x)

Ruby PHP Python

for x in 0..10 puts 'The number is: %d' % [x]end

0.upto(10).each { |x| printf('The number is: %d', x)}

11.times do |x| puts "The number is: #{x}"end

Thursday, October 10, 13

Page 8: D-Talk: What's awesome about Ruby 2.x and Rails 4

(0..10).each do |x| puts "The number is: #{x}"end

<?php for ($x=0; $x<=10; $x++){ echo "The number is: $x";}?>

for x in range(0, 11): print 'The number is: %d' % (x)

Ruby PHP Python

for x in 0..10 puts 'The number is: %d' % [x]end

0.upto(10).each { |x| printf('The number is: %d', x)}

11.times do |x| puts "The number is: #{x}"end

puts (0..10).map{|x| "The number is: #{x}"}

Thursday, October 10, 13

Page 9: D-Talk: What's awesome about Ruby 2.x and Rails 4

(0..10).each do |x| puts "The number is: #{x}"end

<?php for ($x=0; $x<=10; $x++){ echo "The number is: $x";}?>

for x in range(0, 11): print 'The number is: %d' % (x)

Ruby PHP Python

for x in 0..10 puts 'The number is: %d' % [x]end

0.upto(10).each { |x| printf('The number is: %d', x)}

11.times do |x| puts "The number is: #{x}"end

puts (0..10).map{|x| "The number is: #{x}"}

puts ("The number is N\n" * 11).gsub('N').with_index{|_,i| i}

Thursday, October 10, 13

Page 10: D-Talk: What's awesome about Ruby 2.x and Rails 4

RUBY 2.0Thursday, October 10, 13

Page 11: D-Talk: What's awesome about Ruby 2.x and Rails 4

KEYWORD ARGUMENTI# Ruby < 2def run(options = {}) options.reverse_merge!( opt1: "default" ) raise ArgumentError unless options.keys.in?([:opt1, :opt2]) options[:opt1]end

# Ruby 2def run(opt1: "default", opt2: nil) opt1end

run(opt2: "x")run(opt2: "x", opt3: "y") # ArgumentError

def run(opt1: "default", opt2: nil, **options) opt1end

run(opt2: "x", opt3: "y")

Thursday, October 10, 13

Page 12: D-Talk: What's awesome about Ruby 2.x and Rails 4

MODULE#PREPEND

Thursday, October 10, 13

Page 13: D-Talk: What's awesome about Ruby 2.x and Rails 4

class Bar

def hello puts 1 endend

Bar.new.hello

Bar.ancestors๏ BasicObject๏ Kernel๏ Object๏ Bar

Thursday, October 10, 13

Page 14: D-Talk: What's awesome about Ruby 2.x and Rails 4

class Foo def hello puts 'hello' endend

class Bar < Foo

def hello puts 1 super endend

Bar.new.hello

Bar.ancestors๏ BasicObject๏ Kernel๏ Object๏ Foo๏ Bar

Thursday, October 10, 13

Page 15: D-Talk: What's awesome about Ruby 2.x and Rails 4

module FooBar def hello puts 2 super endend

class Foo def hello puts 'hello' endend

class Bar < Foo include FooBar def hello puts 1 super endend

Bar.new.hello

Bar.ancestors๏ BasicObject๏ Kernel๏ Object๏ Foo๏ FooBar๏ Bar

Thursday, October 10, 13

Page 16: D-Talk: What's awesome about Ruby 2.x and Rails 4

module FooBar def hello puts 2 super endend

class Foo def hello puts 'hello' endend

class Bar < Foo include FooBar def hello puts 1 super endend

Bar.new.hello

Bar.ancestors๏ BasicObject๏ Kernel๏ Object๏ Foo๏ FooBar๏ Bar

12hello

Thursday, October 10, 13

Page 17: D-Talk: What's awesome about Ruby 2.x and Rails 4

module FooBar def hello puts 2 super endend

class Foo def hello puts 'hello' endend

class Bar < Foo prepend FooBar def hello puts 1 super endend

Bar.new.hello

Bar.ancestors๏ BasicObject๏ Kernel๏ Object๏ Foo๏ Bar๏ FooBar

Thursday, October 10, 13

Page 18: D-Talk: What's awesome about Ruby 2.x and Rails 4

module FooBar def hello puts 2 super endend

class Foo def hello puts 'hello' endend

class Bar < Foo prepend FooBar def hello puts 1 super endend

Bar.new.hello

Bar.ancestors๏ BasicObject๏ Kernel๏ Object๏ Foo๏ Bar๏ FooBar

21hello

Thursday, October 10, 13

Page 19: D-Talk: What's awesome about Ruby 2.x and Rails 4

LAZY ENUMERATIONS

Thursday, October 10, 13

Page 20: D-Talk: What's awesome about Ruby 2.x and Rails 4

ENUMERATIONS

[1, 2, 3, 4] .map { |i| i * 2 } # => [2, 4, 6, 8] .take(2) # => [2, 4] .reduce(&:+) # => 6

Thursday, October 10, 13

Page 21: D-Talk: What's awesome about Ruby 2.x and Rails 4

LAZY

[1, 2, 3, 4] .lazy # => #<Enumerator::Lazy: [1, 2, 3, 4]> .map { |i| i * 2 } # => #<Enumerator::Lazy: [1, 2, 3, 4]>:map> .take(2) # => #<Enumerator::Lazy: #<Enumerator::Lazy: [1, 2, 3, 4]>:map>:take(2)> .reduce(&:+) # => 6

Thursday, October 10, 13

Page 22: D-Talk: What's awesome about Ruby 2.x and Rails 4

LAZY

(1..Float::INFINITY) .lazy .map { |i| i * 2 } .take(2) .reduce(&:+)

Thursday, October 10, 13

Page 23: D-Talk: What's awesome about Ruby 2.x and Rails 4

GENERATIONAL GARBAGE COLLECTOR

If you care about GC, just use JRuby.

Thursday, October 10, 13

Page 24: D-Talk: What's awesome about Ruby 2.x and Rails 4

GENERATIONAL GARBAGE COLLECTOR

If you care about GC, just use JRuby.

switch to JRubyThursday, October 10, 13

Page 25: D-Talk: What's awesome about Ruby 2.x and Rails 4

RUBY 2.0: REFINEMENTS

Meh.

Thursday, October 10, 13

Page 26: D-Talk: What's awesome about Ruby 2.x and Rails 4

RUBY 2.1: REFINEMENTSmodule BalkanString refine String do def debalkanize ActiveSupport::Inflector.transliterate(self) end endend

class User < ActiveRecord::Base using BalkanString

def name @name.debalkanize if @name endend

"test".debalkanize # NoMethodError

Thursday, October 10, 13

Page 27: D-Talk: What's awesome about Ruby 2.x and Rails 4

RUBY ON RAILS

Thursday, October 10, 13

Page 28: D-Talk: What's awesome about Ruby 2.x and Rails 4

Django146,869 LOC

Rails162,084 LOC

CakePHP147,738 LOC

Lines of code

Thursday, October 10, 13

Page 29: D-Talk: What's awesome about Ruby 2.x and Rails 4

100% MODULAREN

Thursday, October 10, 13

Page 30: D-Talk: What's awesome about Ruby 2.x and Rails 4

Rails‣lepilo

‣Model

‣View‣Controller

Thursday, October 10, 13

Page 31: D-Talk: What's awesome about Ruby 2.x and Rails 4

Rails‣lepilo

‣Model

‣View‣Controller

Thursday, October 10, 13

Page 32: D-Talk: What's awesome about Ruby 2.x and Rails 4

Rails‣railties 16,017 LOC ‣activesupport 25,710 LOC

‣Model

‣View‣Controller

Thursday, October 10, 13

Page 33: D-Talk: What's awesome about Ruby 2.x and Rails 4

Rails‣railties‣activesupport‣Model

‣View‣Controller

Thursday, October 10, 13

Page 34: D-Talk: What's awesome about Ruby 2.x and Rails 4

Rails‣railties‣activesupport‣activemodel 5,694 LOC

‣activerecord 53,435 LOC

‣View‣Controller

Thursday, October 10, 13

Page 35: D-Talk: What's awesome about Ruby 2.x and Rails 4

Rails‣railties‣activesupport‣activemodel‣activerecord‣View‣Controller

Thursday, October 10, 13

Page 36: D-Talk: What's awesome about Ruby 2.x and Rails 4

Rails‣railties‣activesupport‣activemodel‣activerecord‣actionview 22,501 LOC

‣Controller

Thursday, October 10, 13

Page 37: D-Talk: What's awesome about Ruby 2.x and Rails 4

Rails‣railties‣activesupport‣activemodel‣activerecord‣actionview‣Controller

Thursday, October 10, 13

Page 38: D-Talk: What's awesome about Ruby 2.x and Rails 4

Rails‣railties‣activesupport‣activemodel‣activerecord‣actionview‣actionpack 35,538 LOC

Thursday, October 10, 13

Page 39: D-Talk: What's awesome about Ruby 2.x and Rails 4

Rails‣railties‣activesupport‣activemodel‣activerecord‣actionview‣actionpack

Thursday, October 10, 13

Page 40: D-Talk: What's awesome about Ruby 2.x and Rails 4

DEPLOY

Unicorn

Rainbows!

Thursday, October 10, 13

Page 41: D-Talk: What's awesome about Ruby 2.x and Rails 4

RAILS 4

Thursday, October 10, 13

Page 42: D-Talk: What's awesome about Ruby 2.x and Rails 4

TURBOLINKSVideo (57:10)

Rails Conf 2013 Patterns of Basecamp's Application Architecture by David Heinemeier Hansson

http://www.youtube.com/watch?v=yhseQP52yIY

Thursday, October 10, 13

Page 43: D-Talk: What's awesome about Ruby 2.x and Rails 4

THREAD SAFEJBoss, 200 threads, OK

Thursday, October 10, 13

Page 44: D-Talk: What's awesome about Ruby 2.x and Rails 4

DON’T JUST TRY, TRY!# Rails 3

[10].try(:count) # => 15.try(:count) # NoMethodErrornil.try(:count) # => nil

# Rails 4

5.try(:count) # => nil5.try!(:count) # NoMethodErrornil.try(:count) #=> nilnil.try!(:count) #=> nil

Thursday, October 10, 13

Page 45: D-Talk: What's awesome about Ruby 2.x and Rails 4

ACTIONCONTROLLER::LIVEclass MyController < ActionController::Base include ActionController::Live

def stream response.headers['Content-Type'] = 'text/event-stream' 100.times { response.stream.write "hello world\n" sleep 1 } ensure response.stream.close endend

avtomatsko naredi thread

Thursday, October 10, 13

Page 46: D-Talk: What's awesome about Ruby 2.x and Rails 4

POSTGRESQLArray

Thursday, October 10, 13

Page 47: D-Talk: What's awesome about Ruby 2.x and Rails 4

POSTGRESQL ARRAY

class CreateDocuments < ActiveRecord::Migration def change create_table :documents do |t| t.string :title t.string :tags, array: true, default: [] t.timestamps end endend

Thursday, October 10, 13

Page 48: D-Talk: What's awesome about Ruby 2.x and Rails 4

POSTGRESQL ARRAY

Document.create(title: "PostgreSQL", tags: ["pg","rails"])Document.where("'pg' = ANY (tags)")

Thursday, October 10, 13

Page 49: D-Talk: What's awesome about Ruby 2.x and Rails 4

POSTGRESQLhstore (Hash/Dictionary)

Thursday, October 10, 13

Page 50: D-Talk: What's awesome about Ruby 2.x and Rails 4

POSTGRESQL HSTORE

class AddHstoreExtension < ActiveRecord::Migration def up execute 'CREATE EXTENSION hstore' end

def down execute 'DROP EXTENSION hstore' endend

class AddPropertiesToComics < ActiveRecord::Migration def change add_column :comics, :properties, :hstore endend

Thursday, October 10, 13

Page 51: D-Talk: What's awesome about Ruby 2.x and Rails 4

POSTGRESQL HSTORE

class Comic < ActiveRecord::Baseend

Comic.create(properties: { issued: 1.year.ago })

Comic.where("properties -> 'issued' > ?", 2.years.ago)

Thursday, October 10, 13

Page 52: D-Talk: What's awesome about Ruby 2.x and Rails 4

POSTGRESQL HSTORE

class Comic < ActiveRecord::Base store_accessor :properties, :issuedend

Comic.create(issued: 1.year.ago)

Comic.where("properties -> 'issued' > ?", 2.years.ago)

Ali sploh rabiš hstore v tem primeru?Thursday, October 10, 13

Page 53: D-Talk: What's awesome about Ruby 2.x and Rails 4

ACTIVERECORDIn Rails 4

Thursday, October 10, 13

Page 54: D-Talk: What's awesome about Ruby 2.x and Rails 4

SCOPES

class User < ActiveRecord::Base # Rails 3 scope :newest, where("created_at > ?", 1.week.ago)

# Rails 4 scope :newest, -> { where("created_at > ?", 1.week.ago) }end

Thursday, October 10, 13

Page 55: D-Talk: What's awesome about Ruby 2.x and Rails 4

WHERE.NOT

# Rails 3User.where('role != ?', 'admin')User.where('nickname IS NOT NULL')

# Rails 4User.where.not(role: 'admin')User.where.not(nickname: nil)

Thursday, October 10, 13

Page 56: D-Talk: What's awesome about Ruby 2.x and Rails 4

MIGRACIJE PREJclass ChangeProductsPrice < ActiveRecord::Migration def up change_table :products do |t| t.change :price, :string end end

def down change_table :products do |t| t.change :price, :integer end endend

Thursday, October 10, 13

Page 57: D-Talk: What's awesome about Ruby 2.x and Rails 4

MIGRACIJEclass ChangeProductsPrice < ActiveRecord::Migration def change reversible do |dir| change_table :products do |t| dir.up { t.change :price, :string } dir.down { t.change :price, :integer } end end endend

Thursday, October 10, 13

Page 58: D-Talk: What's awesome about Ruby 2.x and Rails 4

NONE RELATIONclass User < ActiveRecord::Base scope :with_role, ->(role) { if User.role_valid? role where(role: role) else none end }end

User.with_role(params[:role]).where.not(nick: nil)

Thursday, October 10, 13

Page 59: D-Talk: What's awesome about Ruby 2.x and Rails 4

STRONG PARAMETERS

Thursday, October 10, 13

Page 60: D-Talk: What's awesome about Ruby 2.x and Rails 4

PROBLEM

• User

• name

• is_admin

Thursday, October 10, 13

Page 61: D-Talk: What's awesome about Ruby 2.x and Rails 4

RAILS 3class User < ActiveRecord::Base attr_accessible :nameend

# controller

user.update_attributes(params[:user])

# admin

user.update_attributes(is_admin: true) # :-(

user.is_admin = trueuser.save

Thursday, October 10, 13

Page 62: D-Talk: What's awesome about Ruby 2.x and Rails 4

RAILS 3

class User < ActiveRecord::Base attr_accessible :nameend

# controller

user.update_attributes(params[:user])

v čem je v resnici problem?

Thursday, October 10, 13

Page 63: D-Talk: What's awesome about Ruby 2.x and Rails 4

RAILS 3

class User < ActiveRecord::Base attr_accessible :nameend

# controller

user.update_attributes(params[:user])

user.update_attributes(is_admin: true) # :-(

non-sanitizeduser input

Thursday, October 10, 13

Page 64: D-Talk: What's awesome about Ruby 2.x and Rails 4

STRONG PARAMETERS

class User < ActiveRecord::Baseend

# controller

def user_params params.require(:user).permit(:name)end

user.update_attributes(user_params)

user.update_attributes(params[:user])# error: Unpermitted parameters

user.update_attributes(is_admin: true) # OK :-)

Thursday, October 10, 13

Page 65: D-Talk: What's awesome about Ruby 2.x and Rails 4

CACHING

• avtomatski expire pri spremembi modela

• avtomatski expire pri spremembi viewa

• russian doll (nested) caching

• Rails Conf 2013 Patterns of Basecamp's Application Architecture by David Heinemeier Hansson

• http://www.youtube.com/watch?v=yhseQP52yIY

Thursday, October 10, 13

Page 66: D-Talk: What's awesome about Ruby 2.x and Rails 4

ACTIVESUPPORT::CONCERNmodule Commentable extend ActiveSupport::Concern

included do has_many :comments end

def has_comments? !comments.empty? end

module ClassMethods def comments_count joins(:comments) .references(:comments) .pluck("COUNT(comments.id)") end endend

class Post < ActiveRecord::Base include Commentableend

User.posts.comment_countPost.first.commentsPost.first.has_comments?

Rails 4 ima direktorij za concerne.Whatever.

Thursday, October 10, 13

Page 67: D-Talk: What's awesome about Ruby 2.x and Rails 4

THE END

Thursday, October 10, 13