D-Talk: What's awesome about Ruby 2.x and Rails 4
-
Upload
jan-berdajs -
Category
Technology
-
view
870 -
download
1
description
Transcript of D-Talk: What's awesome about Ruby 2.x and Rails 4
RUBY 2.X
Thursday, October 10, 13
2012Thursday, October 10, 13
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
(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
(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
(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
(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
(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
(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
RUBY 2.0Thursday, October 10, 13
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
MODULE#PREPEND
Thursday, October 10, 13
class Bar
def hello puts 1 endend
Bar.new.hello
Bar.ancestors๏ BasicObject๏ Kernel๏ Object๏ Bar
Thursday, October 10, 13
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
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
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
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
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
LAZY ENUMERATIONS
Thursday, October 10, 13
ENUMERATIONS
[1, 2, 3, 4] .map { |i| i * 2 } # => [2, 4, 6, 8] .take(2) # => [2, 4] .reduce(&:+) # => 6
Thursday, October 10, 13
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
LAZY
(1..Float::INFINITY) .lazy .map { |i| i * 2 } .take(2) .reduce(&:+)
Thursday, October 10, 13
GENERATIONAL GARBAGE COLLECTOR
If you care about GC, just use JRuby.
Thursday, October 10, 13
GENERATIONAL GARBAGE COLLECTOR
If you care about GC, just use JRuby.
switch to JRubyThursday, October 10, 13
RUBY 2.0: REFINEMENTS
Meh.
Thursday, October 10, 13
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
RUBY ON RAILS
Thursday, October 10, 13
Django146,869 LOC
Rails162,084 LOC
CakePHP147,738 LOC
Lines of code
Thursday, October 10, 13
100% MODULAREN
Thursday, October 10, 13
Rails‣lepilo
‣Model
‣View‣Controller
Thursday, October 10, 13
Rails‣lepilo
‣Model
‣View‣Controller
Thursday, October 10, 13
Rails‣railties 16,017 LOC ‣activesupport 25,710 LOC
‣Model
‣View‣Controller
Thursday, October 10, 13
Rails‣railties‣activesupport‣Model
‣View‣Controller
Thursday, October 10, 13
Rails‣railties‣activesupport‣activemodel 5,694 LOC
‣activerecord 53,435 LOC
‣View‣Controller
Thursday, October 10, 13
Rails‣railties‣activesupport‣activemodel‣activerecord‣View‣Controller
Thursday, October 10, 13
Rails‣railties‣activesupport‣activemodel‣activerecord‣actionview 22,501 LOC
‣Controller
Thursday, October 10, 13
Rails‣railties‣activesupport‣activemodel‣activerecord‣actionview‣Controller
Thursday, October 10, 13
Rails‣railties‣activesupport‣activemodel‣activerecord‣actionview‣actionpack 35,538 LOC
Thursday, October 10, 13
Rails‣railties‣activesupport‣activemodel‣activerecord‣actionview‣actionpack
Thursday, October 10, 13
DEPLOY
Unicorn
Rainbows!
Thursday, October 10, 13
RAILS 4
Thursday, October 10, 13
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
THREAD SAFEJBoss, 200 threads, OK
Thursday, October 10, 13
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
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
POSTGRESQLArray
Thursday, October 10, 13
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
POSTGRESQL ARRAY
Document.create(title: "PostgreSQL", tags: ["pg","rails"])Document.where("'pg' = ANY (tags)")
Thursday, October 10, 13
POSTGRESQLhstore (Hash/Dictionary)
Thursday, October 10, 13
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
POSTGRESQL HSTORE
class Comic < ActiveRecord::Baseend
Comic.create(properties: { issued: 1.year.ago })
Comic.where("properties -> 'issued' > ?", 2.years.ago)
Thursday, October 10, 13
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
ACTIVERECORDIn Rails 4
Thursday, October 10, 13
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
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
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
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
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
STRONG PARAMETERS
Thursday, October 10, 13
PROBLEM
• User
• name
• is_admin
Thursday, October 10, 13
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
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
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
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
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
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
THE END
Thursday, October 10, 13