Upload
alexey-nayden
View
2.430
Download
0
Embed Size (px)
Citation preview
Wider Than Rails: Lightweight Ruby
SolutionsAlexey Nayden, EvilMartians.com
RubyC 2011
суббота, 5 ноября 11 г.
Lightweight != Fast
Lightweight ≈ Simple
суббота, 5 ноября 11 г.
Less code=
Easier to maintain=
(often)
Faster
суббота, 5 ноября 11 г.
Motives to travel light
• Production performance
• Complexity overhead
• Learning curve
• More flexibility
• Self-improvement
суббота, 5 ноября 11 г.
Do you always need all of that?
$ lsapp/config/db/doc/Gemfilelib/logpublic/RakefileREADMEscript/spec/test/tmp/vendor/www/Gemfile.lock.rspecconfig.ru
суббота, 5 ноября 11 г.
Do you always need all of that?
$ lsapp/config/db/doc/Gemfilelib/logpublic/RakefileREADMEscript/spec/test/tmp/vendor/www/Gemfile.lock.rspecconfig.ru
суббота, 5 ноября 11 г.
Lightweight plan
• Replace components of your framework
• Inject lightweight tools
• Migrate to a different platform
• Don't forget to be consistent
суббота, 5 ноября 11 г.
ActiveRecord? Sequel!
• http://sequel.rubyforge.org
• Sequel is a gem providing both raw SQL and neat ORM interfaces
• 18 DBMS support out of the box
• 25—50% faster than ActiveRecord
• 100% ActiveModel compliant
суббота, 5 ноября 11 г.
Sequel ORMclass UsersController < ApplicationController before_filter :find_user, :except => [:create] def create @user = User.new(params[:user]) end protected def find_user @user = User[params[:id]] endend
суббота, 5 ноября 11 г.
Sequel Modelclass User < Sequel::Model one_to_many :comments subset(:active){comments_count > 20}
plugin :validation_helpers def validate super validates_presence [:email, :name] validates_unique :email validates_integer :age if new? end
def before_create self.created_at ||= Time.now # however there's a plugin super # for timestamping endend
суббота, 5 ноября 11 г.
Raw SQLDB.fetch("SELECT * FROM albums WHERE name LIKE :pattern", :pattern=>'A%') do |row| puts row[:name]end
DB.run "CREATE TABLE albums (id integer primary key, name varchar(255))"
db(:legacy).fetch(" SELECT (SELECT count(*) FROM activities WHERE ACTION = 'logged_in' AND DATE(created_at) BETWEEN DATE(:start) AND DATE(:end) ) AS login_count, (SELECT count(*) FROM users WHERE (DATE(created_at) BETWEEN DATE(:start) AND DATE(:end)) AND (activated_at IS NOT NULL) ) AS user_count", :start => start_date, :end => end_date)
суббота, 5 ноября 11 г.
Benchmarks
суббота, 5 ноября 11 г.
Clean frontend with Zepto.js
• http://zeptojs.com
• JS framework for with a jQ-compatible syntax and API
• Perfect for rich mobile (esp. iOS) web-apps, but works in any modern browser except IE
• 7.5 Kb at the moment (vs. 31 Kb jQ)
• Officially — beta, but used at mobile version of Groupon ⇒ production-ready
суббота, 5 ноября 11 г.
Good old $$('p>span').html('Hello, RubyC').css('color:red');
Well-known syntax$('p').bind('click', function(){ $('span', this).css('color:red');});
Touch UI? No problem!$('some selector').tap(function(){ ... });$('some selector').doubleTap(function(){ ... });$('some selector').swipeRight(function(){ ... });$('some selector').pinch(function(){ ... });
суббота, 5 ноября 11 г.
Xtra Xtra Small: Rack
• Rack is a specification of a minimal Ruby API that models HTTP
• One might say Rack is a CGI in a Ruby world
• Only connects a webserver with your «app» (actually it can be just a lambda!)
суббота, 5 ноября 11 г.
Rack• You need to have an object with a method
call(env)
• It should return an array with 3 elements[status_code, headers, body]
• So now you can connect it with any webserver that supports Rackrequire ‘thin’Rack::Handler::Thin.run(app, :Port => 4000)
• Lightweight webapp completed
суббота, 5 ноября 11 г.
Rack App Exampleclass ServerLoad def call(env) [200, {"Content-Type" => "text/plain"}, ["uptime | cut -f 11 -d ' '"]] endend
суббота, 5 ноября 11 г.
Metal. Rack on Rails
• ActionController::Metal is a way to get a valid Rack app from a controller
• A bit more comfortable dealing with Rack inside Rails
• You still can include any parts of ActionController stack inside your metal controller
• Great for API`s
суббота, 5 ноября 11 г.
Metallic APIclass ApiController < ActionController::Metal include AbstractController::Callbacks include ActionController::Helpers include Devise::Controllers::Helpers before_filter :require_current_user
def history content_type = "application/json" recipient = User.find(params[:user_id]) messages = Message.between(current_user, recipient)
if params[:start_date] response_body = messages.after(params[:start_date]).to_json else response_body = messages.recent.to_json end endend
суббота, 5 ноября 11 г.
Sinatra• Sinatra should be considered as a compact
framework (however they prefer calling it DSL) replacing ActionController and router
• You still can include ActiveRecord, ActiveSupport or on the other side — include Sinatra app inside Rails app
• But you can also go light with Sequel / DataMapper and plaintext / XML / JSON output
суббота, 5 ноября 11 г.
require 'rubygems'require 'sinatra'
get '/' do haml :indexend
post '/signup' do Spam.deliver(params[:email])end
mime :json, 'application/json'get '/events/recent.json' do content_type :json Event.recent.to_jsonend
Sinatra
суббота, 5 ноября 11 г.
Padrino. DSL evolves to a framework
• http://www.padrinorb.com/
• Based on a Sinatra and brings LIKE-A-BOSS comfort to a Sinatra development process
• Fully supports 6 ORMs, 5 JS libs, 2 rendering engines, 6 test frameworks, 2 stylesheet engines and 2 mocking libs out of the box
• Still remains quick and simple
суббота, 5 ноября 11 г.
Padrino blog
class SampleBlog < Padrino::Application register Padrino::Helpers register Padrino::Mailer register SassInitializer
get "/" do "Hello World!" end
get :about, :map => '/about_us' do render :haml, "%p This is a sample blog" end
end
$ padrino g project sample_blog -t shoulda -e haml \ -c sass -s jquery -d activerecord -b
суббота, 5 ноября 11 г.
Posts controller
SampleBlog.controllers :posts do get :index, :provides => [:html, :rss, :atom] do @posts = Post.all(:order => 'created_at desc') render 'posts/index' end
get :show, :with => :id do @post = Post.find_by_id(params[:id]) render 'posts/show' endend
суббота, 5 ноября 11 г.
A little bit of useless benchmarking
• We take almost plain «Hello World» application and runab -‐c 10 -‐n 1000
• rack 1200 rps
• sinatra 600 rps
• padrino 570 rps
• rails 140 rps
суббота, 5 ноября 11 г.
ToolsThey don't need to be huge and slow
суббота, 5 ноября 11 г.
Pow
• http://pow.cx/
• A 37signals Rack-based webserver for developer needs
• One-line installer, unobtrusive, fast and only serves web-apps, nothing else
• cd ~/.powln -‐s /path/to/app
суббота, 5 ноября 11 г.
rbenv
• https://github.com/sstephenson/rbenv
• Small, quick, doesn't modify shell commands, UNIX-way
• rbenv global 1.9.2-‐p290cd /path/to/apprbenv local jruby-‐1.6.4
суббота, 5 ноября 11 г.
One more thing...
суббота, 5 ноября 11 г.
Ruby is not a silver bullet
You should always consider different platforms and languages: Erlang, Scala, .NET and even C++
суббота, 5 ноября 11 г.
Ruby is not a silver bullet
You should always consider different platforms and languages: Erlang, Scala, .NET and even C++
Don't miss Timothy Tsvetkov's speech tomorrow
суббота, 5 ноября 11 г.