+ All Categories
Home > Technology > Techmosis Rails

Techmosis Rails

Date post: 29-Jan-2018
Category:
Upload: jan-berkel
View: 1,131 times
Download: 0 times
Share this document with a friend
78
techmosis @last.fm, feb 2009 Ruby on Rails
Transcript
Page 1: Techmosis Rails

techmosis @last.fm, feb 2009

Ruby on Rails

Page 2: Techmosis Rails

... some fundamentals

Page 3: Techmosis Rails

“one stack” approach[M+V+C]

Page 4: Techmosis Rails

“thou shalt not repeat thyself”

(it’s a religion)

Page 5: Techmosis Rails

convention overconfiguration(table names)

Page 6: Techmosis Rails

brought established softwareengineering principles

into “scripting” environments

Page 7: Techmosis Rails

model: ActiveRecord

Page 8: Techmosis Rails

class Foo < ActiveRecord::Base belongs_to :bar # insert rails magic hereend

Page 9: Techmosis Rails

# standard queryFoo.find(:all, :conditions=>["name=?", "kittens"])

# provided by ARFoo.find_by_name("kittens")

# avoid N+1Foo.find(:all, :include=>:bar)

# customFoo.find_by_sql("select foos.* from foos where....")

Page 10: Techmosis Rails

view: erb or haml?

Page 11: Techmosis Rails

erb: php style <%= foo %>

Page 12: Techmosis Rails

haml: nested structure

Page 13: Techmosis Rails

!!!%html{ :xmlns => "http://www.w3.org/1999/xhtml", "xml:lang" => "en" } %head %meta{ "http-equiv" => "content-type", :content => "text/html; charset=utf-8" }/ %title= page_title = render :partial => "shared/icon" = stylesheet_link_tag 'screen', :media => 'screen' /[if IE] %style{:type=>"text/css"} * html { overflow-y: scroll; overflow-x: hidden; } = javascript_include_tag 'prototype' = javascript_include_tag 'lowpro' = javascript_include_tag 'velcro'

= controller_assets /[if IE] = stylesheet_link_tag 'ie', :media => 'screen' %body %div#page %div#content = @content_for_layout %div#footer = render :partial => "shared/footer"

Page 14: Techmosis Rails

testing: rspec{model, view, controller}

Page 15: Techmosis Rails

BDD(behaviour

driven development)

Page 16: Techmosis Rails

# model specdescribe "generating api key" do it "should create an api key entry in the db" do lambda { @howard.generate_api_key! }.should change(ApiKey, :count).by(1) endend

# controller specdescribe "an admin" do describe "with a valid API key" do before do @howard.generate_api_key! end it "should be able to fetch the latest graph" do get :latest, :params=>{:api_key => @howard.api_key}, :response=>200 end it "should be able to fetch meta data" do #... end endend

Page 17: Techmosis Rails

deployment

Page 18: Techmosis Rails

historically very painful(mod_fcgi, mongrel+

mod_proxy_balancer,mod_rewrite...)

too many options...

Page 19: Techmosis Rails

complicated to set up.

Page 20: Techmosis Rails

<VirtualHost *:80> ServerName <%= servername>> DocumentRoot "/rails_root/public"

<Directory "/rails_root/public"> Options FollowSymLinks AllowOverride None Order allow,deny Allow from all Header append Cache-Control "private, must-revalidate, max-age=0" </Directory>

<Proxy balancer://<%= clustername %>> <% startport.upto(startport + servers - 1) do |p| -%> BalancerMember http://127.0.0.1:<%= p %> <% end -%> ProxySet lbmethod=bytraffic ProxySet maxattempts=5 </Proxy> ProxyTimeout 300

RewriteEngine On # Check for maintenance file and redirect all requests RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f RewriteCond %{SCRIPT_FILENAME} !maintenance.html RewriteRule ^.*$ /system/maintenance.html [L]

# Rewrite index to check for static RewriteRule ^/$ /index.html [QSA]

# Rewrite to check for Rails cached page RewriteRule ^([^.]+)$ $1.html [QSA]

# Redirect all non-static requests to cluster RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f RewriteRule ^/(.*)$ balancer://<%= clustername %>%{REQUEST_URI} [P,QSA,L]</VirtualHost>

Page 21: Techmosis Rails

btw: don’t use mongrel

(it leaks memory)

Page 22: Techmosis Rails

a new standard emerges:rack

Page 23: Techmosis Rails

not tied to rails, can be used with many ruby

based frameworks

Page 24: Techmosis Rails

app.call(env)

call a method...

Page 25: Techmosis Rails

[200, 'Content-Type'=>'text/plain', 'Hello World']

which returns an array with 3 elements...

Page 26: Techmosis Rails

for apache2 there is...

Page 27: Techmosis Rails

mod_rails / mod_rack(phusion passenger)

Page 28: Techmosis Rails

it’s quite simple...

Page 29: Techmosis Rails

LoadModule passenger_module /usr/lib/passenger/mod_passenger.soPassengerRoot /usrPassengerRuby /usr/bin/ruby1.8

<VirtualHost *:80> ServerName myserver.com DocumentRoot "/rails_root/public"</VirtualHost>

Page 30: Techmosis Rails

but...

Page 31: Techmosis Rails

how to get the code deployed?

Page 32: Techmosis Rails

capistrano

Page 33: Techmosis Rails

what cap does for you:

• remote code checkout via VCS

• shell execution on remote servers (in parallel)

• rollback to last release (symlink)

• extensible (not just for rails!)

Page 34: Techmosis Rails

set :repository, "http://myrepo.com/myapp/trunk/"

role :web, "www.example.com"role :db, "db1.example.com", :primary => true

desc "reloads apache config"task :reload , :roles=>:web do sudo "/etc/init.d/httpd reload", :pty => trueend

Page 35: Techmosis Rails

monitoring apps: god

(“like monit, but awesome”)

Page 36: Techmosis Rails

start_port = 3000count = 5

(start_port...start_port+count).each do |port| God.watch do |w| w.start = "sh -c 'mongrel_rails start -p #{port} -c #{RAILS_ROOT}" w.interval = 5.seconds w.grace = 5.seconds

# restart if memory or cpu is too high w.restart_if do |restart| restart.condition(:memory_usage) do |c| c.interval = 20 c.above = 500 * 1024 # max_mem MB c.times = [3, 5] end end w.notify = “[email protected]” endend

Page 37: Techmosis Rails

exception_notifier

Page 38: Techmosis Rails
Page 39: Techmosis Rails

console

Page 40: Techmosis Rails

scaling rails

Page 41: Techmosis Rails

processes vs threads

Page 42: Techmosis Rails

def dispatch if ActionController::Base.allow_concurrency dispatch_unlocked else @@guard.synchronize do dispatch_unlocked end end end

new in rails 2.2: multithreading!

(finally...)

Page 43: Techmosis Rails

new: connection pooling(actually required formultithreaded apps)

Page 44: Techmosis Rails

what’s good / interesting?

Page 45: Techmosis Rails

active community (some call it “ghetto”)

Page 46: Techmosis Rails

some really good plugins(acts_as_*)

Page 47: Techmosis Rails

quick development +testing

Page 48: Techmosis Rails

ActiveRecord scopes

Page 49: Techmosis Rails

Post.with_scope(:find => {:conditions => ["user_id = ?", current_user.id]} do @user_posts = Post.find(:all)end

Page 50: Techmosis Rails

easy RESTful development

Page 51: Techmosis Rails

map.resources :tasks, :member => { :run => :post }, :collection => { :run_all => :post }

# tasks => GET /tasks# new_task => PUT /tasks/new# update_task(@task) => POST /tasks/1/update# run_task(@task) => POST /tasks/1/run# run_all_tasks => POST /tasks/run_all

class TasksController < ApplicationController def index @task = Task.find(:all) end def update @task = Task.find(params[:id]) @task.update_attributes!(params[:task]) end def run @task = Task.find(params[:id]) @task.run! endend

Page 52: Techmosis Rails

ActiveResource

Page 53: Techmosis Rails

class Task < ActiveResource::Base self.site = "http://api.example.com"end

@task = Task.new(:when=>Time.now)@task.save # POST http://api.example.com/tasks/[email protected] # => 1

@task = Task.find(1) # GET http://api.example.com/tasks/1.xml

Page 54: Techmosis Rails

creating feeds

Page 55: Techmosis Rails

class TasksController < ApplicationController def index @tasks = Task.find(:all) respond_to do |format| format.html format.atom end endend

# from tasks/index.atom.builderatom_feed(:url => formatted_tasks_url(:atom)) do |feed| feed.title("Tasks") feed.updated(Time.now.utc) for task in @tasks feed.entry(task) do |entry| entry.title(task.name) entry.content(task.content) end endend

Page 56: Techmosis Rails

what’s bad?

Page 57: Techmosis Rails

too much magic(method_missing, really...)

Page 58: Techmosis Rails

monkey patching / metaprogramming

(too much !)

Page 59: Techmosis Rails

module ActiveSupport #:nodoc: module CoreExtensions #:nodoc: module Array #:nodoc: # Makes it easier to access parts of an array. module Access # Equal to <tt>self[1]</tt>. def second self[1] end

# Equal to <tt>self[2]</tt>. def third self[2] end

# Equal to <tt>self[3]</tt>. def fourth self[3] end #.... #WTF? # Equal to <tt>self[41]</tt>. Also known as accessing "the reddit". def forty_two self[41] end end endend

Page 60: Techmosis Rails

monolithic architecture

Page 61: Techmosis Rails

“If you’re not doing it the ‘Rails way’...

Page 62: Techmosis Rails

...ur doing it wrong!”

Page 63: Techmosis Rails

DHH

Page 64: Techmosis Rails

native extensions =deployment headaches

Page 65: Techmosis Rails

alternatively...

Page 66: Techmosis Rails

deploy your app on the JVM: JRuby on Rails

Page 67: Techmosis Rails

you need: ActiveRecord-JDBC(more options)

Page 68: Techmosis Rails

integrate with java libraries

Page 69: Techmosis Rails

deploy on: jetty, glassfish, ...

Page 70: Techmosis Rails

it’s faster!(about twice as fast)

Page 71: Techmosis Rails

future

Page 72: Techmosis Rails

rails3 aka merb

Page 73: Techmosis Rails

merb?(mongrel+erb)

Page 74: Techmosis Rails

“clean-room” implementationof rails

Page 75: Techmosis Rails

modular design, choice of frameworks

(no “merb way”)

Page 76: Techmosis Rails

merb-slices(apps in django?)

Page 77: Techmosis Rails

current trends

Page 78: Techmosis Rails

micro-frameworks: sinatra


Recommended