SlideShare une entreprise Scribd logo
1  sur  190
Ruby 101
Your favorite language sucks. language sucks.
Ruby is the greatest language ever made.
Ruby is the greatest language ever made. And if you disagree, you’re wrong.
February 24, 1993
Yukihiro “Matz” Matsumoto まつもとゆきひろ
Yukihiro “Matz” Matsumoto “ I wanted a scripting language that was more powerful than Perl, and more object-oriented than Python. That's why I decided to design my own language.”
Yukihiro “Matz” Matsumoto “ I hope to see Ruby help every programmer in the world to be productive, to enjoy programming, and to be happy. “ That is the primary purpose of the Ruby language.”
Yukihiro “Matz” Matsumoto “ Often people, especially computer engineers, focus on the machines. They think, ‘By doing this, the machine will run faster. By doing this, the machine will run more effectively. By doing this, the machine will something something something.’ They are focusing on machines. But, in fact, we need to focus on humans.”
for  ( var  i = 0 ; i < 3 ; i ++ ) {   alert ( 'Hello, world!' ); }
for  ( var  i = 0 ; i < 3 ; i ++ ) {   alert ( 'Hello, world!' ); } 3 .times  do   puts  'Hello, world!' end
var  people  =  [ 'Rob' , 'Eugene' , 'Crystal' ]; for  ( var  i = 0 ; i < people. length ; i ++ ) {   alert (people[i]  +   ' loves Ruby' ); }
var  people  =  [ 'Rob' , 'Eugene' , 'Crystal' ]; for  ( var  i = 0 ; i < people. length ; i ++ ) {   alert (people[i]  +   ' loves Ruby' ); } [ 'Rob' , 'Eugene' , 'Crystal' ].each  do  | name |   puts  &quot;#{name} loves Ruby&quot; end
var  today  =   new   Date (); today. setDate (today. getDate ()  +   2 );
var  today  =   new   Date (); today. setDate (today. getDate ()  +   2 ); 2 .days.from_now
Yukihiro “Matz” Matsumoto “ Sometimes people jot down pseudo-code on paper. If that pseudo-code runs directly on their computers, it’s best, isn’t it? “ Ruby tries to be like that, like pseudo-code that runs.”
REPL
REPL Read - Eval - Print - Loop
REPL Read - Eval - Print - Loop irb
REPL Read - Eval - Print - Loop irb interactive ruby
rob$
rob$ irb
rob$ irbruby-1.9.2 :001 >
rob$ irbruby-1.9.2 :001 > people = ['Rob','Eugene','Crystal']
rob$ irbruby-1.9.2 :001 > people = ['Rob','Eugene','Crystal'] => [&quot;Rob&quot;, &quot;Eugene&quot;, &quot;Crystal&quot;] ruby-1.9.2 :002 >
rob$ irbruby-1.9.2 :001 > people = ['Rob','Eugene','Crystal'] => [&quot;Rob&quot;, &quot;Eugene&quot;, &quot;Crystal&quot;] ruby-1.9.2 :002 > people.length
rob$ irbruby-1.9.2 :001 > people = ['Rob','Eugene','Crystal'] => [&quot;Rob&quot;, &quot;Eugene&quot;, &quot;Crystal&quot;] ruby-1.9.2 :002 > people.length => 3 ruby-1.9.2 :003 >
rob$ irbruby-1.9.2 :001 > people = ['Rob','Eugene','Crystal'] => [&quot;Rob&quot;, &quot;Eugene&quot;, &quot;Crystal&quot;] ruby-1.9.2 :002 > people.length => 3 ruby-1.9.2 :003 > people.last
rob$ irbruby-1.9.2 :001 > people = ['Rob','Eugene','Crystal'] => [&quot;Rob&quot;, &quot;Eugene&quot;, &quot;Crystal&quot;] ruby-1.9.2 :002 > people.length => 3 ruby-1.9.2 :003 > people.last => &quot;Crystal&quot; ruby-1.9.2 :004 >
rob$ irbruby-1.9.2 :001 > people = ['Rob','Eugene','Crystal'] => [&quot;Rob&quot;, &quot;Eugene&quot;, &quot;Crystal&quot;] ruby-1.9.2 :002 > people.length => 3 ruby-1.9.2 :003 > people.last => &quot;Crystal&quot; ruby-1.9.2 :004 > people.reverse
rob$ irbruby-1.9.2 :001 > people = ['Rob','Eugene','Crystal'] => [&quot;Rob&quot;, &quot;Eugene&quot;, &quot;Crystal&quot;] ruby-1.9.2 :002 > people.length => 3 ruby-1.9.2 :003 > people.last => &quot;Crystal&quot; ruby-1.9.2 :004 > people.reverse => [&quot;Crystal&quot;, &quot;Eugene&quot;, &quot;Rob&quot;] ruby-1.9.2 :005 >
The Basics
count  =   42
count  =   42 amount  =   23.83
count  =   42 amount  =   23.83 language  =   'Ruby'
count  =   42 amount  =   23.83 language  =   'Ruby' text  =   &quot;#{language} is the best!&quot;
count  =   42 amount  =   23.83 language  =   'Ruby' text  =   &quot;#{language} is the best!&quot; people  =   [ 'Rob' , 'Eugene' , 'Crystal' ]
count  =   42 amount  =   23.83 language  =   'Ruby' text  =   &quot;#{language} is the best!&quot; people  =   [ 'Rob' , 'Eugene' , 'Crystal' ] person  =  {  :name  =>  'Rob' ,   :gender   =>  'male'  }
count  =   42 amount  =   23.83 language  =   'Ruby' text  =   &quot;#{language} is the best!&quot; people  =   [ 'Rob' , 'Eugene' , 'Crystal' ] person  =  {  :name  =>  'Rob' ,   :gender   =>  'male'  } this  =   true
count  =   42 amount  =   23.83 language  =   'Ruby' text  =   &quot;#{language} is the best!&quot; people  =   [ 'Rob' , 'Eugene' , 'Crystal' ] person  =  {  :name  =>  'Rob' ,   :gender   =>  'male'  } this  =   true that  =   false
count  =   42 amount  =   23.83 language  =   'Ruby' text  =   &quot;#{language} is the best!&quot; people  =   [ 'Rob' , 'Eugene' , 'Crystal' ] person  =  {  :name  =>  'Rob' ,   :gender   =>  'male'  } this  =   true that  =   false nothing   =   nil
[ 'Rob' , 'Eugene' , 'Crystal' ].each  do  | name |   puts  &quot;#{name} loves Ruby&quot; end
[ 'Rob' , 'Eugene' , 'Crystal' ].each  do  | name |   puts  &quot;#{name} loves Ruby&quot; end Iterators
[ 'Rob' , 'Eugene' , 'Crystal' ].each  do  | name |   puts  &quot;#{name} loves Ruby&quot; end Iterators each  find  collect  each_with_index  reject  inject
$ ( 'li' ).each( function (index) {   alert ( 'index=' + index); });
$ ( 'li' ).each( function (index) {   alert ( 'index=' + index); }); an_array.each  do  | item |   puts  &quot;item=#{item}&quot; end
Loops?
Conditionals
if   person.has_red_hair?   Sun .burn person end
if   person.has_red_hair?   Sun .burn person end unless  car.sugar_in_gas_tank?   car.start end
if   person.has_red_hair?   Sun .burn person end unless  car.sugar_in_gas_tank?   car.start end 15 .times { wash_hands }  if  person.ocd?
if   person.has_red_hair?   Sun .burn person end unless  car.sugar_in_gas_tank?   car.start end 15 .times { wash_hands }  if  person.ocd? car.accelerate  unless   TrafficLight .is_red?
if  just_worked_out  and  date_tonight   take_a_shower end
if  just_worked_out  and  date_tonight   take_a_shower end if   love_mom   or   just_drunk   get_a_tattoo end
if  just_worked_out  and  date_tonight   take_a_shower end if   love_mom   or   just_drunk   get_a_tattoo end if  taco_bell?  and not  pepto_bismol_nearby? get_to_bathroom! end
!
airlines   =   [ 'Southwest' , 'United' , 'Delta' ]
airlines   =   [ 'Southwest' , 'United' , 'Delta' ] airlines.reverse => [ 'Delta' , 'United' , 'Southwest' ]
airlines   =   [ 'Southwest' , 'United' , 'Delta' ] airlines.reverse => [ 'Delta' , 'United' , 'Southwest' ] puts airlines => [ 'Southwest' , 'United' , 'Delta' ]
airlines   =   [ 'Southwest' , 'United' , 'Delta' ] airlines.reverse => [ 'Delta' , 'United' , 'Southwest' ] puts airlines => [ 'Southwest' , 'United' , 'Delta' ] airlines.reverse! => [ 'Delta' , 'United' , 'Southwest' ]
airlines   =   [ 'Southwest' , 'United' , 'Delta' ] airlines.reverse => [ 'Delta' , 'United' , 'Southwest' ] puts airlines => [ 'Southwest' , 'United' , 'Delta' ] airlines.reverse! => [ 'Delta' , 'United' , 'Southwest' ] puts airlines => [ 'Delta' , 'United' , 'Southwest' ]
everything  is an object
‘ Rob’.class
‘ Rob’.class  => String
‘ Rob’.class  => String 42.class
‘ Rob’.class  => String 42.class  => Fixnum
‘ Rob’.class  => String 42.class  => Fixnum (23.45).class
‘ Rob’.class  => String 42.class  => Fixnum (23.45).class  => Float
‘ Rob’.class  => String 42.class  => Fixnum (23.45).class  => Float true.class
‘ Rob’.class  => String 42.class  => Fixnum (23.45).class  => Float true.class  => TrueClass
‘ Rob’.class  => String 42.class  => Fixnum (23.45).class  => Float true.class  => TrueClass nil.class
‘ Rob’.class  => String 42.class  => Fixnum (23.45).class  => Float true.class  => TrueClass nil.class  => NilClass
‘ Rob’.class  => String 42.class  => Fixnum (23.45).class  => Float true.class  => TrueClass nil.class  => NilClass String.class
‘ Rob’.class  => String 42.class  => Fixnum (23.45).class  => Float true.class  => TrueClass nil.class  => NilClass String.class  => Class
‘ Rob’.class  => String 42.class  => Fixnum (23.45).class  => Float true.class  => TrueClass nil.class  => NilClass String.class  => Class Class.class
‘ Rob’.class  => String 42.class  => Fixnum (23.45).class  => Float true.class  => TrueClass nil.class  => NilClass String.class  => Class Class.class  => Class
‘ Rob’.class  => String 42.class  => Fixnum (23.45).class  => Float true.class  => TrueClass nil.class  => NilClass String.class  => Class Class.class  => Class Class.superclass
‘ Rob’.class  => String 42.class  => Fixnum (23.45).class  => Float true.class  => TrueClass nil.class  => NilClass String.class  => Class Class.class  => Class Class.superclass  => Module
‘ Rob’.class  => String 42.class  => Fixnum (23.45).class  => Float true.class  => TrueClass nil.class  => NilClass String.class  => Class Class.class  => Class Class.superclass  => Module Module.superclass
‘ Rob’.class  => String 42.class  => Fixnum (23.45).class  => Float true.class  => TrueClass nil.class  => NilClass String.class  => Class Class.class  => Class Class.superclass  => Module Module.superclass  => Object
‘ Rob’.class  => String 42.class  => Fixnum (23.45).class  => Float true.class  => TrueClass nil.class  => NilClass String.class  => Class Class.class  => Class Class.superclass  => Module Module.superclass  => Object Object.superclass
‘ Rob’.class  => String 42.class  => Fixnum (23.45).class  => Float true.class  => TrueClass nil.class  => NilClass String.class  => Class Class.class  => Class Class.superclass  => Module Module.superclass  => Object Object.superclass  => BasicObject
‘ Rob’.class  => String 42.class  => Fixnum (23.45).class  => Float true.class  => TrueClass nil.class  => NilClass String.class  => Class Class.class  => Class Class.superclass  => Module Module.superclass  => Object Object.superclass  => BasicObject BasicObject.superclass
‘ Rob’.class  => String 42.class  => Fixnum (23.45).class  => Float true.class  => TrueClass nil.class  => NilClass String.class  => Class Class.class  => Class Class.superclass  => Module Module.superclass  => Object Object.superclass  => BasicObject BasicObject.superclass  => nil
Class, Object, Module and all other classes are instances of a class  Class . Class, Module and Object have a circular dependency as they are in the core of the OO model
Introspection
42.methods
42.methods [:!, :!=, :!~, :%, :&, :*, :**, :+, :+@, :-, :-@, :/, :<, :<<, :<=, :<=>, :==, :===, :=~, :>, :>=, :>>, :[], :^, :__id__, :__send__, :abs, :abs2, :angle, :arg, :between?, :ceil, :chr, :class, :clone, :coerce, :conj, :conjugate, :define_singleton_method, :denominator, :display, :div, :divmod, :downto, :dup, :enum_for, :eql?, :equal?, :even?, :extend, :fdiv, :floor, :freeze, :frozen?, :gcd, :gcdlcm, :hash, :i, :imag, :imaginary, :initialize_clone, :initialize_dup, :inspect, :instance_eval, :instance_exec, :instance_of?, :instance_variable_defined?, :instance_variable_get, :instance_variable_set, :instance_variables, :integer?, :is_a?, :kind_of?, :lcm, :magnitude, :method, :methods, :modulo, :next, :nil?, :nonzero?, :numerator, :object_id, :odd?, :ord, :phase, :polar, :pred, :private_methods, :protected_methods, :public_method, :public_methods, :public_send, :quo, :rationalize, :real, :real?, :rect, :rectangular, :remainder, :respond_to?, :respond_to_missing?, :round, :send, :singleton_class, :singleton_method_added, :singleton_methods, :size, :step, :succ, :taint, :tainted?, :tap, :times, :to_c, :to_enum, :to_f, :to_i, :to_int, :to_r, :to_s, :truncate, :trust, :untaint, :untrust, :untrusted?, :upto, :zero?, :|, :~]
42.methods [:!, :!=, :!~, :%, :&, :*, :**, :+, :+@, :-, :-@, :/, :<, :<<, :<=, :<=>, :==, :===, :=~, :>, :>=, :>>, :[], :^, :__id__, :__send__, :abs, :abs2, :angle, :arg, :between?, :ceil, :chr, :class, :clone, :coerce, :conj, :conjugate, :define_singleton_method, :denominator, :display, :div, :divmod, :downto, :dup, :enum_for, :eql?, :equal?, :even?, :extend, :fdiv, :floor, :freeze, :frozen?, :gcd, :gcdlcm, :hash, :i, :imag, :imaginary, :initialize_clone, :initialize_dup, :inspect, :instance_eval, :instance_exec, :instance_of?, :instance_variable_defined?, :instance_variable_get, :instance_variable_set,  :instance_variables , :integer?, :is_a?, :kind_of?, :lcm, :magnitude, :method, :methods, :modulo, :next, :nil?, :nonzero?, :numerator, :object_id, :odd?, :ord, :phase, :polar, :pred,  :private_methods , :protected_methods, :public_method,  :public_methods , :public_send, :quo, :rationalize, :real, :real?, :rect, :rectangular, :remainder,  :respond_to? , :respond_to_missing?, :round,  :send , :singleton_class, :singleton_method_added, :singleton_methods, :size, :step, :succ, :taint, :tainted?, :tap, :times, :to_c, :to_enum, :to_f, :to_i, :to_int, :to_r, :to_s, :truncate, :trust, :untaint, :untrust, :untrusted?, :upto, :zero?, :|, :~]
var   method   =   'first_name' eval ( 'person.'  +  method)
var   method   =   'first_name' eval ( 'person.'  +  method) method   =   'first_name' person.send(method)
2 + 2
2 + 2 2.+(2)
2 + 2 2.+(2) 2.send('+',2)
Syntactic Sugar
2 == 2
2 == 2 2.==(2)
2 == 2 2.==(2) 2.send('==',2)
Ruby removes the cruft
car   =   Vehicle . new ( 'honda' ,  'civic' , {  :interior  =>  'beige'  }) car   =   Vehicle . new   'honda' ,   'civic' ,  :interior  =>  'beige'
Beautiful code
class   Person   attr_accessor   'gender' , 'eyes' , 'chin' , 'name'   def   initialize ( gender,eyes,chin )   @gender   =  gender   @eyes   =   eyes   @chin   =   chin   end end
class   Person   attr_accessor   'gender' , 'eyes' , 'chin' , 'name'   def   initialize ( gender,eyes,chin )   @gender   =  gender   @eyes   =   eyes   @chin   =   chin   end end rob   =   Person . new   'male' , 'blue' , 'square'
class   Person   attr_accessor   'gender' , 'eyes' , 'chin' , 'name'   def   initialize ( gender,eyes,chin )   @gender   =  gender   @eyes   =   eyes   @chin   =   chin   end end rob   =   Person . new   'male' , 'blue' , 'square' aimee   =   Person . new   'female' , 'brown' , 'cleft'
class   Person   attr_accessor   'gender' , 'eyes' , 'chin' , 'name'   def   initialize ( gender,eyes,chin )   @gender   =  gender   @eyes   =   eyes   @chin   =   chin   end end rob   =   Person . new   'male' , 'blue' , 'square' aimee   =   Person . new   'female' , 'brown' , 'cleft'
class   Person   def   + ( other_person )   gene_pool   =   [ self ,other_person]   Person . new   selection(gene_pool, 'gender' ),    selection(gene_pool, 'eyes' ),    selection(gene_pool, 'chin' )   end     def   selection ( gene_pool,feature )   return   gene_pool[rand(gene_pool.size)].send feature   end private   'selection' end
baby   =   rob   +   aimee
baby   =   rob   +   aimee baby.name   =   'Jack'
 
baby   =   rob   +   aimee baby.name   =   'Jack' baby.name=( 'Jack' )
baby   =   rob   +   aimee baby.name   =   'Jack' baby.name=( 'Jack' ) baby.inspect
baby   =   rob   +   aimee baby.name   =   'Jack' baby.name=( 'Jack' ) baby.inspect #<Person:0x0000010083fdf0 @gender=&quot;male&quot;, @eyes=&quot;blue&quot;, @chin=&quot;cleft&quot;, @name=&quot;Jack&quot;>
“ When I am working on a problem I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong.” —  R. Buckminster Fuller
return   gene_pool[rand(gene_pool.size)].send feature
return   gene_pool[rand(gene_pool.size)].send feature class   Array   def   random   return  self [rand( self .length)]   end end
return   gene_pool[rand(gene_pool.size)].send feature class   Array   def   random   return  self [rand( self .length)]   end end return  gene_pool.random.send feature
unless  []. respond_to ?  'random' class   Array   def   random   return  self [rand( self .length)]   end   end end
Monkey Patching!!1!one!!!
David Heinemeier Hansson (DHH) “ Why Ruby” http://confreaks.net/system/assets/datas/694/original/431-rubyconf2010-keynote-why-ruby-small.mp4?1291226733
“ UNIX was not designed to stop its users from doing stupid things, as that would also stop them from doing clever things.” — Doug Gwyn
“ There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code.”  — Anonymous
class   Array   def   random   return  self [rand( self .length)]   end end class   Person   attr_accessor   'gender' , 'eyes' , 'chin' , 'name'   def   initialize ( gender,eyes,chin )   @gender   =  gender   @eyes   =   eyes   @chin   =   chin   end def   + ( other_person )   gene_pool   =   [ self ,other_person]   Person . new   selection(gene_pool, 'gender' ),    selection(gene_pool, 'eyes' ),    selection(gene_pool, 'chin' )   end     def   selection ( gene_pool,feature )   return   gene_pool.random.send feature   end private   'selection' end
using System;using System.Collections.Concurrent;using System.Collections.Specialized;using System.ComponentModel.Composition;using System.Diagnostics;using System.IO;using System.IO.Compression;using System.Net;using System.Text.RegularExpressions;using System.Threading;using System.Linq;using Newtonsoft.Json;using NLog;using Raven.Abstractions.Data;using Raven.Abstractions.Exceptions;using Raven.Abstractions.MEF;using Raven.Http.Abstractions;using Raven.Http.Exceptions;using Raven.Http.Extensions;using Formatting = Newtonsoft.Json.Formatting;namespace Raven.Http{ public abstract class HttpServer : IDisposable  { private const int MaxConcurrentRequests = 192; protected readonly IResourceStore DefaultResourceStore;  protected readonly IRavenHttpConfiguration DefaultConfiguration;  private readonly ThreadLocal<string> currentTenantId = new ThreadLocal<string>();  private readonly ThreadLocal<IResourceStore> currentDatabase = new ThreadLocal<IResourceStore>();  private readonly ThreadLocal<IRavenHttpConfiguration> currentConfiguration = new ThreadLocal<IRavenHttpConfiguration>();  protected readonly ConcurrentDictionary<string, IResourceStore> ResourcesStoresCache =  new ConcurrentDictionary<string, IResourceStore>(StringComparer.InvariantCultureIgnoreCase);  private readonly ConcurrentDictionary<string, DateTime> databaseLastRecentlyUsed = new ConcurrentDictionary<string, DateTime>();
public int NumberOfRequests { get { return Thread.VolatileRead(ref physicalRequestsCount); } } [ImportMany] public OrderedPartCollection<AbstractRequestResponder> RequestResponders { get; set; }  public IRavenHttpConfiguration Configuration  {  get  {  return DefaultConfiguration;  }  }  public abstract Regex TenantsQuery { get; }  private HttpListener listener; private static readonly Logger logger = LogManager.GetCurrentClassLogger();  private int reqNum;  // concurrent requests  // we set 1/4 aside for handling background tasks  private readonly SemaphoreSlim concurretRequestSemaphore = new SemaphoreSlim(MaxConcurrentRequests);  private Timer databasesCleanupTimer; private int physicalRequestsCount; public bool HasPendingRequests { get { return concurretRequestSemaphore.CurrentCount != MaxConcurrentRequests; } } protected HttpServer(IRavenHttpConfiguration configuration, IResourceStore resourceStore)  {
DefaultResourceStore = resourceStore;  DefaultConfiguration = configuration;  configuration.Container.SatisfyImportsOnce(this);  foreach (var requestResponder in RequestResponders)  {  requestResponder.Value.Initialize(() => currentDatabase.Value, () => currentConfiguration.Value, () => currentTenantId.Value, this);  }  }  #region IDisposable Members  public void Dispose()  {  databasesCleanupTimer.Dispose();  if (listener != null && listener.IsListening)  listener.Stop();  foreach (var documentDatabase in ResourcesStoresCache)  {  documentDatabase.Value.Dispose();  }  }  #endregion  public void Start()  {  listener = new HttpListener();  string virtualDirectory = DefaultConfiguration.VirtualDirectory;  if (virtualDirectory.EndsWith(&quot;/&quot;) == false)  virtualDirectory = virtualDirectory + &quot;/&quot;;  listener.Prefixes.Add(&quot;http://&quot; + (DefaultConfiguration.HostName ?? &quot;+&quot;) + &quot;:&quot; + DefaultConfiguration.Port + virtualDirectory);
switch (DefaultConfiguration.AnonymousUserAccessMode)  {  case AnonymousUserAccessMode.None:  listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication;  break;  case AnonymousUserAccessMode.All:  listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication |  AuthenticationSchemes.Anonymous;  listener.AuthenticationSchemeSelectorDelegate = request =>  { if(request.RawUrl.StartsWith(&quot;/admin&quot;,StringComparison.InvariantCultureIgnoreCase)) return AuthenticationSchemes.IntegratedWindowsAuthentication;  return AuthenticationSchemes.Anonymous;  };  break;  case AnonymousUserAccessMode.Get:  listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication |  AuthenticationSchemes.Anonymous;  listener.AuthenticationSchemeSelectorDelegate = request =>  {  return IsGetRequest(request.HttpMethod, request.Url.AbsolutePath) ? AuthenticationSchemes.Anonymous | AuthenticationSchemes.IntegratedWindowsAuthentication :  AuthenticationSchemes.IntegratedWindowsAuthentication;  };  break;  default:  throw new ArgumentException(&quot;Cannot understand access mode: &quot; + DefaultConfiguration.AnonymousUserAccessMode);  }  databasesCleanupTimer = new Timer(CleanupDatabases, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));  listener.Start();  listener.BeginGetContext(GetContext, null);  }
private void CleanupDatabases(object state)  {  var databasesToCleanup = databaseLastRecentlyUsed  .Where(x=>(DateTime.Now - x.Value).TotalMinutes > 10)  .Select(x=>x.Key)  .ToArray();  foreach (var db in databasesToCleanup)  {  DateTime _;  databaseLastRecentlyUsed.TryRemove(db, out _);  IResourceStore database;  if(ResourcesStoresCache.TryRemove(db, out database))  database.Dispose();  }  }  private void GetContext(IAsyncResult ar)  {  IHttpContext ctx;  try  {  ctx = new HttpListenerContextAdpater(listener.EndGetContext(ar), DefaultConfiguration);  //setup waiting for the next request  listener.BeginGetContext(GetContext, null);  }  catch (InvalidOperationException)  {  // can't get current request / end new one, probably  // listner shutdown  return;  }  catch (HttpListenerException)  {  // can't get current request / end new one, probably  // listner shutdown  return;  }
if (concurretRequestSemaphore.Wait(TimeSpan.FromSeconds(5)) == false)  {  HandleTooBusyError(ctx);  return;  }  try  {  Interlocked.Increment(ref physicalRequestsCount);  HandleActualRequest(ctx);  }  finally  {  concurretRequestSemaphore.Release();  }  }  public void HandleActualRequest(IHttpContext ctx)  {  var sw = Stopwatch.StartNew();  bool ravenUiRequest = false;  try  {  ravenUiRequest = DispatchRequest(ctx);  }  catch (Exception e)  {  HandleException(ctx, e); if (ShouldLogException(e)) logger.WarnException(&quot;Error on request&quot;, e);  }  finally  {  try  {  FinalizeRequestProcessing(ctx, sw, ravenUiRequest);  }  catch (Exception e)  {  logger.ErrorException(&quot;Could not finalize request properly&quot;, e);  }
protected virtual bool ShouldLogException(Exception exception) { return true; } private void FinalizeRequestProcessing(IHttpContext ctx, Stopwatch sw, bool ravenUiRequest) { LogHttpRequestStatsParams logHttpRequestStatsParam = null; try { logHttpRequestStatsParam = new LogHttpRequestStatsParams( sw,  ctx.Request.Headers,  ctx.Request.HttpMethod,  ctx.Response.StatusCode,  ctx.Request.Url.PathAndQuery); } catch (Exception e) { logger.WarnException(&quot;Could not gather information to log request stats&quot;, e); } ctx.FinalizeResonse(); sw.Stop(); if (ravenUiRequest || logHttpRequestStatsParam == null)  return; LogHttpRequestStats(logHttpRequestStatsParam); ctx.OutputSavedLogItems(logger); } private void LogHttpRequestStats(LogHttpRequestStatsParams logHttpRequestStatsParams)  { // we filter out requests for the UI because they fill the log with information // we probably don't care about them anyway. That said, we do output them if they take too // long.
if (logHttpRequestStatsParams.Headers[&quot;Raven-Timer-Request&quot;] == &quot;true&quot; && logHttpRequestStatsParams.Stopwatch.ElapsedMilliseconds <= 25)  return;  var curReq = Interlocked.Increment(ref reqNum);  logger.Debug(&quot;Request #{0,4:#,0}: {1,-7} - {2,5:#,0} ms - {5,-10} - {3} - {4}&quot;,    curReq,    logHttpRequestStatsParams.HttpMethod,    logHttpRequestStatsParams.Stopwatch.ElapsedMilliseconds,    logHttpRequestStatsParams.ResponseStatusCode,    logHttpRequestStatsParams.RequestUri,    currentTenantId.Value);  }  private void HandleException(IHttpContext ctx, Exception e)  {  try  {  if (e is BadRequestException)  HandleBadRequest(ctx, (BadRequestException)e);  else if (e is ConcurrencyException)  HandleConcurrencyException(ctx, (ConcurrencyException)e);  else if (TryHandleException(ctx, e))  return;  else  HandleGenericException(ctx, e);  }  catch (Exception)  {  logger.ErrorException(&quot;Failed to properly handle error, further error handling is ignored&quot;, e);  }  }  protected abstract bool TryHandleException(IHttpContext ctx, Exception exception);
private static void HandleTooBusyError(IHttpContext ctx)  {  ctx.Response.StatusCode = 503;  ctx.Response.StatusDescription = &quot;Service Unavailable&quot;;  SerializeError(ctx, new  {  Url = ctx.Request.RawUrl,  Error = &quot;The server is too busy, could not acquire transactional access&quot;  });  }  private static void HandleGenericException(IHttpContext ctx, Exception e)  {  ctx.Response.StatusCode = 500;  ctx.Response.StatusDescription = &quot;Internal Server Error&quot;;  SerializeError(ctx, new  {  Url = ctx.Request.RawUrl,  Error = e.ToString()  });  }  private static void HandleBadRequest(IHttpContext ctx, BadRequestException e)  {  ctx.SetStatusToBadRequest();  SerializeError(ctx, new  {  Url = ctx.Request.RawUrl,  e.Message,  Error = e.Message  });  }
private static void HandleConcurrencyException(IHttpContext ctx, ConcurrencyException e)  {  ctx.Response.StatusCode = 409;  ctx.Response.StatusDescription = &quot;Conflict&quot;;  SerializeError(ctx, new  {  Url = ctx.Request.RawUrl,  e.ActualETag,  e.ExpectedETag,  Error = e.Message  });  }  protected static void SerializeError(IHttpContext ctx, object error)  {  var sw = new StreamWriter(ctx.Response.OutputStream);  new JsonSerializer().Serialize(new JsonTextWriter(sw)  {  Formatting = Formatting.Indented,  }, error);  sw.Flush();  }  private bool DispatchRequest(IHttpContext ctx)  {  if (AssertSecurityRights(ctx) == false)  return false;  SetupRequestToProperDatabase(ctx);  CurrentOperationContext.Headers.Value = ctx.Request.Headers;  try  {  OnDispatchingRequest(ctx);  if (DefaultConfiguration.HttpCompression)  AddHttpCompressionIfClientCanAcceptIt(ctx);
AddAccessControlAllowOriginHeader(ctx);  foreach (var requestResponderLazy in RequestResponders)  {  var requestResponder = requestResponderLazy.Value;  if (requestResponder.WillRespond(ctx))  {  requestResponder.Respond(ctx);  return requestResponder.IsUserInterfaceRequest;  }  }  ctx.SetStatusToBadRequest();  if (ctx.Request.HttpMethod == &quot;HEAD&quot;)  return false;  ctx.Write(  @&quot;<html>  <body>  <h1>Could not figure out what to do</h1>  <p>Your request didn't match anything that Raven knows to do, sorry...</p>  </body></html>&quot;);  }  finally  {  CurrentOperationContext.Headers.Value = new NameValueCollection();  currentDatabase.Value = DefaultResourceStore;  currentConfiguration.Value = DefaultConfiguration;  }  return false;  }  protected virtual void OnDispatchingRequest(IHttpContext ctx){}
private void SetupRequestToProperDatabase(IHttpContext ctx)  {  var requestUrl = ctx.GetRequestUrlForTenantSelection();  var match = TenantsQuery.Match(requestUrl);  if (match.Success == false)  {  currentTenantId.Value = Constants.DefaultDatabase;  currentDatabase.Value = DefaultResourceStore;  currentConfiguration.Value = DefaultConfiguration;  }  else  {  var tenantId = match.Groups[1].Value;  IResourceStore resourceStore;  if(TryGetOrCreateResourceStore(tenantId, out resourceStore))  {  databaseLastRecentlyUsed.AddOrUpdate(tenantId, DateTime.Now, (s, time) => DateTime.Now); if (string.IsNullOrEmpty(Configuration.VirtualDirectory) == false && Configuration.VirtualDirectory != &quot;/&quot;) { ctx.AdjustUrl(Configuration.VirtualDirectory + match.Value); }  else { ctx.AdjustUrl(match.Value); }  currentTenantId.Value = tenantId;  currentDatabase.Value = resourceStore;  currentConfiguration.Value = resourceStore.Configuration;  }  else  {  throw new BadRequestException(&quot;Could not find a database named: &quot; + tenantId);  }  }  }
protected abstract bool TryGetOrCreateResourceStore(string name, out IResourceStore database);  private void AddAccessControlAllowOriginHeader(IHttpContext ctx)  {  if (string.IsNullOrEmpty(DefaultConfiguration.AccessControlAllowOrigin))  return;  ctx.Response.AddHeader(&quot;Access-Control-Allow-Origin&quot;, DefaultConfiguration.AccessControlAllowOrigin);  }  private static void AddHttpCompressionIfClientCanAcceptIt(IHttpContext ctx)  {  var acceptEncoding = ctx.Request.Headers[&quot;Accept-Encoding&quot;];  if (string.IsNullOrEmpty(acceptEncoding))  return;  // gzip must be first, because chrome has an issue accepting deflate data  // when sending it json text  if ((acceptEncoding.IndexOf(&quot;gzip&quot;, StringComparison.InvariantCultureIgnoreCase) != -1))  {  ctx.SetResponseFilter(s => new GZipStream(s, CompressionMode.Compress, true));  ctx.Response.AddHeader(&quot;Content-Encoding&quot;,&quot;gzip&quot;);  }  else if (acceptEncoding.IndexOf(&quot;deflate&quot;, StringComparison.InvariantCultureIgnoreCase) != -1)  {  ctx.SetResponseFilter(s => new DeflateStream(s, CompressionMode.Compress, true));  ctx.Response.AddHeader(&quot;Content-Encoding&quot;, &quot;deflate&quot;);  }  }  private bool AssertSecurityRights(IHttpContext ctx)  { if (DefaultConfiguration.AnonymousUserAccessMode == AnonymousUserAccessMode.None && IsInvalidUser(ctx)) { ctx.SetStatusToUnauthorized(); return false; }
IHttpRequest httpRequest = ctx.Request;  if (DefaultConfiguration.AnonymousUserAccessMode == AnonymousUserAccessMode.Get &&  IsInvalidUser(ctx) &&  IsGetRequest(httpRequest.HttpMethod, httpRequest.Url.AbsolutePath) == false )  {  ctx.SetStatusToUnauthorized();  return false;  }  return true;  } protected virtual bool IsGetRequest(string httpMethod, string requestPath) { return (httpMethod == &quot;GET&quot; || httpMethod == &quot;HEAD&quot;); } private static bool IsInvalidUser(IHttpContext ctx) { return (ctx.User == null || ctx.User.Identity == null || ctx.User.Identity.IsAuthenticated == false); } public void ResetNumberOfRequests() { Interlocked.Exchange(ref reqNum, 0); Interlocked.Exchange(ref physicalRequestsCount, 0); }  }} 517 lines of code
webserver  =   TCPServer . new ( '127.0.0.1' ,  3000 ) while  (session   =  webserver.accept)   session.print  &quot;HTTP/1.1 200/OK  Content-type:text/html  &quot;   request  =  session.gets   filename  =  request.match( /  (.*?)   / )[ 1 ] filename  =   'index.html'   if   filename  ==   ''   begin   session.print  File .read(filename)   rescue   Errno :: ENOENT   session.print  'File not found'   end   session.close end
“ There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies and the other way is to make it so complicated that there are no obvious deficiencies.” — C.A.R. Hoare
class   Person   def   + ( other_person )   gene_pool   =   [ self ,other_person]   Person . new   selection(gene_pool, 'gender' ),    selection(gene_pool, 'eyes' ),    selection(gene_pool, 'chin' )   end     def   selection ( gene_pool,feature )   return   gene_pool[rand(gene_pool.size)].send feature   end private   'selection' end
class   Person   def   + ( other_person )   gene_pool   =   [ self ,other_person]   Person . new   selection(gene_pool, 'gender' ),    selection(gene_pool, 'eyes' ),    selection(gene_pool, 'chin' )   end     def   selection ( gene_pool,feature )   return   gene_pool[rand(gene_pool.size)].send feature   end private   'selection' end
class   Person   def   + ( other_person )   gene_pool   =   [ self ,other_person]   Person . new   selection(gene_pool, 'gender' ),    selection(gene_pool, 'eyes' ),    selection(gene_pool, 'chin' )   end     def   selection ( gene_pool,feature )   return   gene_pool[rand(gene_pool.size)].send feature   end private   'selection' end
Implicit return Any statement in Ruby returns the value of the last evaluated expression
ruby-1.9.2 :001 > puts 'Hello, world!'
ruby-1.9.2 :001 > puts 'Hello, world!'Hello, world! => nil  ruby-1.9.2 :002 >
ruby-1.9.2 :001 > puts 'Hello, world!'Hello, world! => nil  ruby-1.9.2 :002 > puts('Hello, world!')
ruby-1.9.2 :001 > puts 'Hello, world!'Hello, world! => nil  ruby-1.9.2 :002 > puts('Hello, world!')Hello, world! => nil  ruby-1.9.2 :003 >
Blabber Talk to your servers via IM
 
gems
rob$
rob$ gem install rails
rob$ gem install rails rob$ gem install httparty json
require   'rubygems' require   'json' require   'httparty'
rob$ irbruby-1.9.2 :001 >
rob$ irbruby-1.9.2 :001 > HTTParty
rob$ irbruby-1.9.2 :001 > HTTPartyNameError: uninitialized constant Object::HTTParty from (irb):1 from /Users/rob/.rvm/rubies/ruby-1.9.2-p180/bin/irb:16:in `<main>'ruby-1.9.2 :002 >
rob$ irbruby-1.9.2 :001 > HTTPartyNameError: uninitialized constant Object::HTTParty from (irb):1 from /Users/rob/.rvm/rubies/ruby-1.9.2-p180/bin/irb:16:in `<main>'ruby-1.9.2 :002 > require 'httparty'
rob$ irbruby-1.9.2 :001 > HTTPartyNameError: uninitialized constant Object::HTTParty from (irb):1 from /Users/rob/.rvm/rubies/ruby-1.9.2-p180/bin/irb:16:in `<main>'ruby-1.9.2 :002 > require 'httparty' => true ruby-1.9.2 :003 >
rob$ irbruby-1.9.2 :001 > HTTPartyNameError: uninitialized constant Object::HTTParty from (irb):1 from /Users/rob/.rvm/rubies/ruby-1.9.2-p180/bin/irb:16:in `<main>'ruby-1.9.2 :002 > require 'httparty' => true ruby-1.9.2 :003 > HTTParty
rob$ irbruby-1.9.2 :001 > HTTPartyNameError: uninitialized constant Object::HTTParty from (irb):1 from /Users/rob/.rvm/rubies/ruby-1.9.2-p180/bin/irb:16:in `<main>'ruby-1.9.2 :002 > require 'httparty' => true ruby-1.9.2 :003 > HTTParty => HTTParty ruby-1.9.2 :004 >
Questions?
Workshop
Command line interface to the Active.com Search API
It should:
[object Object],[object Object]
[object Object],[object Object],[object Object]
[object Object],[object Object],[object Object],[object Object]
[object Object],[object Object],[object Object],[object Object],[object Object]
[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Example
What you need to know
Required Gems require 'json' require 'httparty'
Search API Endpoint http://api.amp.active.com/search?       v=json&          k=keywords&          m=meta:channel%3DRunning&          api_key=wuhmn9ye94xn3xnteudxsavw
HTTP call HTTParty.get(url)
Parse JSON JSON.parse(text) HTTP call HTTParty.get(url)
Get user input user_input = gets
Get user input user_input = gets Remove newlines user_input.chomp
Get user input user_input = gets Print to STDOUT print 'text'puts  'text' Remove newlines user_input.chomp
Iterate through array with index my_array.each_with_index do |item,i| puts “#{item} is at position #{i}” end
Exit exit 0 Iterate through array with index my_array.each_with_index do |item,i| puts “#{item} is at position #{i}” end
Define methods ,[object Object],[object Object],[object Object],Create classes ,[object Object],[object Object],[object Object],[object Object],[object Object]
Questions?
require 'json' require 'httparty' HTTParty.get(url) JSON.parse(text) user_input = gets print 'text' puts 'text' user_input.chomp my_array.each_with_index do |item,i| puts “#{item} is as position #{i}” end http://api.amp.active.com/search?       v=json&          k=keywords&          m=meta:channel%3DRunning&          api_key= wuhmn9ye94xn3xnteudxsavw exit 0
“ I am rarely happier than when spending an entire day programming my computer to perform automatically a task that would otherwise take me a good ten seconds to do by hand.”  —  Douglas Adams
Learning a new language
 
 
EGO
“ Would you rather be a king of fools or a student of masters?”
The End

Contenu connexe

Similaire à Ruby 101 Guide: Everything is an Object

Why Python by Marilyn Davis, Marakana
Why Python by Marilyn Davis, MarakanaWhy Python by Marilyn Davis, Marakana
Why Python by Marilyn Davis, MarakanaMarko Gargenta
 
☣ ppencode ♨
☣ ppencode ♨☣ ppencode ♨
☣ ppencode ♨Audrey Tang
 
LAMP_TRAINING_SESSION_1
LAMP_TRAINING_SESSION_1LAMP_TRAINING_SESSION_1
LAMP_TRAINING_SESSION_1umapst
 
Rochester on Rails: Introduction to Ruby
Rochester on Rails: Introduction to RubyRochester on Rails: Introduction to Ruby
Rochester on Rails: Introduction to RubyJason Morrison
 
[Erlang LT] Regexp Perl And Port
[Erlang LT] Regexp Perl And Port[Erlang LT] Regexp Perl And Port
[Erlang LT] Regexp Perl And PortKeiichi Daiba
 
Erlang with Regexp Perl And Port
Erlang with Regexp Perl And PortErlang with Regexp Perl And Port
Erlang with Regexp Perl And PortKeiichi Daiba
 
WTFin Perl
WTFin PerlWTFin Perl
WTFin Perllechupl
 
Ruby for perl developers
Ruby for perl developersRuby for perl developers
Ruby for perl developersIdo Kanner
 
PERL Unit 6 regular expression
PERL Unit 6 regular expressionPERL Unit 6 regular expression
PERL Unit 6 regular expressionBinsent Ribera
 
MITH Digital Dialogues: Intro to Programming for Humanists (with Ruby)
MITH Digital Dialogues: Intro to Programming for Humanists (with Ruby)MITH Digital Dialogues: Intro to Programming for Humanists (with Ruby)
MITH Digital Dialogues: Intro to Programming for Humanists (with Ruby)joegilbert
 
Freebasing for Fun and Enhancement
Freebasing for Fun and EnhancementFreebasing for Fun and Enhancement
Freebasing for Fun and EnhancementMrDys
 
Presentacion Congreso Medellin, 2008
Presentacion Congreso Medellin, 2008Presentacion Congreso Medellin, 2008
Presentacion Congreso Medellin, 2008Maria Gloria Romero
 
Pengenalan autisme pk
Pengenalan autisme pkPengenalan autisme pk
Pengenalan autisme pkSavithri Savi
 

Similaire à Ruby 101 Guide: Everything is an Object (20)

Learning Ruby
Learning RubyLearning Ruby
Learning Ruby
 
Why Python by Marilyn Davis, Marakana
Why Python by Marilyn Davis, MarakanaWhy Python by Marilyn Davis, Marakana
Why Python by Marilyn Davis, Marakana
 
Faking Data
Faking DataFaking Data
Faking Data
 
☣ ppencode ♨
☣ ppencode ♨☣ ppencode ♨
☣ ppencode ♨
 
LAMP_TRAINING_SESSION_1
LAMP_TRAINING_SESSION_1LAMP_TRAINING_SESSION_1
LAMP_TRAINING_SESSION_1
 
Rochester on Rails: Introduction to Ruby
Rochester on Rails: Introduction to RubyRochester on Rails: Introduction to Ruby
Rochester on Rails: Introduction to Ruby
 
[Erlang LT] Regexp Perl And Port
[Erlang LT] Regexp Perl And Port[Erlang LT] Regexp Perl And Port
[Erlang LT] Regexp Perl And Port
 
Erlang with Regexp Perl And Port
Erlang with Regexp Perl And PortErlang with Regexp Perl And Port
Erlang with Regexp Perl And Port
 
WTFin Perl
WTFin PerlWTFin Perl
WTFin Perl
 
Ruby for perl developers
Ruby for perl developersRuby for perl developers
Ruby for perl developers
 
Proverbs!!
Proverbs!!Proverbs!!
Proverbs!!
 
gonzalo
gonzalogonzalo
gonzalo
 
PERL Unit 6 regular expression
PERL Unit 6 regular expressionPERL Unit 6 regular expression
PERL Unit 6 regular expression
 
Modern Perl
Modern PerlModern Perl
Modern Perl
 
MITH Digital Dialogues: Intro to Programming for Humanists (with Ruby)
MITH Digital Dialogues: Intro to Programming for Humanists (with Ruby)MITH Digital Dialogues: Intro to Programming for Humanists (with Ruby)
MITH Digital Dialogues: Intro to Programming for Humanists (with Ruby)
 
Freebasing for Fun and Enhancement
Freebasing for Fun and EnhancementFreebasing for Fun and Enhancement
Freebasing for Fun and Enhancement
 
Perl Moderno
Perl ModernoPerl Moderno
Perl Moderno
 
Tema2 capa fiaica
Tema2  capa fiaicaTema2  capa fiaica
Tema2 capa fiaica
 
Presentacion Congreso Medellin, 2008
Presentacion Congreso Medellin, 2008Presentacion Congreso Medellin, 2008
Presentacion Congreso Medellin, 2008
 
Pengenalan autisme pk
Pengenalan autisme pkPengenalan autisme pk
Pengenalan autisme pk
 

Dernier

Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGSujit Pal
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 

Dernier (20)

Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAG
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 

Ruby 101 Guide: Everything is an Object

  • 2. Your favorite language sucks. language sucks.
  • 3. Ruby is the greatest language ever made.
  • 4. Ruby is the greatest language ever made. And if you disagree, you’re wrong.
  • 6. Yukihiro “Matz” Matsumoto まつもとゆきひろ
  • 7. Yukihiro “Matz” Matsumoto “ I wanted a scripting language that was more powerful than Perl, and more object-oriented than Python. That's why I decided to design my own language.”
  • 8. Yukihiro “Matz” Matsumoto “ I hope to see Ruby help every programmer in the world to be productive, to enjoy programming, and to be happy. “ That is the primary purpose of the Ruby language.”
  • 9. Yukihiro “Matz” Matsumoto “ Often people, especially computer engineers, focus on the machines. They think, ‘By doing this, the machine will run faster. By doing this, the machine will run more effectively. By doing this, the machine will something something something.’ They are focusing on machines. But, in fact, we need to focus on humans.”
  • 10. for ( var i = 0 ; i < 3 ; i ++ ) { alert ( 'Hello, world!' ); }
  • 11. for ( var i = 0 ; i < 3 ; i ++ ) { alert ( 'Hello, world!' ); } 3 .times do puts 'Hello, world!' end
  • 12. var people = [ 'Rob' , 'Eugene' , 'Crystal' ]; for ( var i = 0 ; i < people. length ; i ++ ) { alert (people[i] + ' loves Ruby' ); }
  • 13. var people = [ 'Rob' , 'Eugene' , 'Crystal' ]; for ( var i = 0 ; i < people. length ; i ++ ) { alert (people[i] + ' loves Ruby' ); } [ 'Rob' , 'Eugene' , 'Crystal' ].each do | name | puts &quot;#{name} loves Ruby&quot; end
  • 14. var today = new Date (); today. setDate (today. getDate () + 2 );
  • 15. var today = new Date (); today. setDate (today. getDate () + 2 ); 2 .days.from_now
  • 16. Yukihiro “Matz” Matsumoto “ Sometimes people jot down pseudo-code on paper. If that pseudo-code runs directly on their computers, it’s best, isn’t it? “ Ruby tries to be like that, like pseudo-code that runs.”
  • 17. REPL
  • 18. REPL Read - Eval - Print - Loop
  • 19. REPL Read - Eval - Print - Loop irb
  • 20. REPL Read - Eval - Print - Loop irb interactive ruby
  • 21. rob$
  • 24. rob$ irbruby-1.9.2 :001 > people = ['Rob','Eugene','Crystal']
  • 25. rob$ irbruby-1.9.2 :001 > people = ['Rob','Eugene','Crystal'] => [&quot;Rob&quot;, &quot;Eugene&quot;, &quot;Crystal&quot;] ruby-1.9.2 :002 >
  • 26. rob$ irbruby-1.9.2 :001 > people = ['Rob','Eugene','Crystal'] => [&quot;Rob&quot;, &quot;Eugene&quot;, &quot;Crystal&quot;] ruby-1.9.2 :002 > people.length
  • 27. rob$ irbruby-1.9.2 :001 > people = ['Rob','Eugene','Crystal'] => [&quot;Rob&quot;, &quot;Eugene&quot;, &quot;Crystal&quot;] ruby-1.9.2 :002 > people.length => 3 ruby-1.9.2 :003 >
  • 28. rob$ irbruby-1.9.2 :001 > people = ['Rob','Eugene','Crystal'] => [&quot;Rob&quot;, &quot;Eugene&quot;, &quot;Crystal&quot;] ruby-1.9.2 :002 > people.length => 3 ruby-1.9.2 :003 > people.last
  • 29. rob$ irbruby-1.9.2 :001 > people = ['Rob','Eugene','Crystal'] => [&quot;Rob&quot;, &quot;Eugene&quot;, &quot;Crystal&quot;] ruby-1.9.2 :002 > people.length => 3 ruby-1.9.2 :003 > people.last => &quot;Crystal&quot; ruby-1.9.2 :004 >
  • 30. rob$ irbruby-1.9.2 :001 > people = ['Rob','Eugene','Crystal'] => [&quot;Rob&quot;, &quot;Eugene&quot;, &quot;Crystal&quot;] ruby-1.9.2 :002 > people.length => 3 ruby-1.9.2 :003 > people.last => &quot;Crystal&quot; ruby-1.9.2 :004 > people.reverse
  • 31. rob$ irbruby-1.9.2 :001 > people = ['Rob','Eugene','Crystal'] => [&quot;Rob&quot;, &quot;Eugene&quot;, &quot;Crystal&quot;] ruby-1.9.2 :002 > people.length => 3 ruby-1.9.2 :003 > people.last => &quot;Crystal&quot; ruby-1.9.2 :004 > people.reverse => [&quot;Crystal&quot;, &quot;Eugene&quot;, &quot;Rob&quot;] ruby-1.9.2 :005 >
  • 33. count = 42
  • 34. count = 42 amount = 23.83
  • 35. count = 42 amount = 23.83 language = 'Ruby'
  • 36. count = 42 amount = 23.83 language = 'Ruby' text = &quot;#{language} is the best!&quot;
  • 37. count = 42 amount = 23.83 language = 'Ruby' text = &quot;#{language} is the best!&quot; people = [ 'Rob' , 'Eugene' , 'Crystal' ]
  • 38. count = 42 amount = 23.83 language = 'Ruby' text = &quot;#{language} is the best!&quot; people = [ 'Rob' , 'Eugene' , 'Crystal' ] person = { :name => 'Rob' , :gender => 'male' }
  • 39. count = 42 amount = 23.83 language = 'Ruby' text = &quot;#{language} is the best!&quot; people = [ 'Rob' , 'Eugene' , 'Crystal' ] person = { :name => 'Rob' , :gender => 'male' } this = true
  • 40. count = 42 amount = 23.83 language = 'Ruby' text = &quot;#{language} is the best!&quot; people = [ 'Rob' , 'Eugene' , 'Crystal' ] person = { :name => 'Rob' , :gender => 'male' } this = true that = false
  • 41. count = 42 amount = 23.83 language = 'Ruby' text = &quot;#{language} is the best!&quot; people = [ 'Rob' , 'Eugene' , 'Crystal' ] person = { :name => 'Rob' , :gender => 'male' } this = true that = false nothing = nil
  • 42. [ 'Rob' , 'Eugene' , 'Crystal' ].each do | name | puts &quot;#{name} loves Ruby&quot; end
  • 43. [ 'Rob' , 'Eugene' , 'Crystal' ].each do | name | puts &quot;#{name} loves Ruby&quot; end Iterators
  • 44. [ 'Rob' , 'Eugene' , 'Crystal' ].each do | name | puts &quot;#{name} loves Ruby&quot; end Iterators each find collect each_with_index reject inject
  • 45. $ ( 'li' ).each( function (index) { alert ( 'index=' + index); });
  • 46. $ ( 'li' ).each( function (index) { alert ( 'index=' + index); }); an_array.each do | item | puts &quot;item=#{item}&quot; end
  • 49. if person.has_red_hair? Sun .burn person end
  • 50. if person.has_red_hair? Sun .burn person end unless car.sugar_in_gas_tank? car.start end
  • 51. if person.has_red_hair? Sun .burn person end unless car.sugar_in_gas_tank? car.start end 15 .times { wash_hands } if person.ocd?
  • 52. if person.has_red_hair? Sun .burn person end unless car.sugar_in_gas_tank? car.start end 15 .times { wash_hands } if person.ocd? car.accelerate unless TrafficLight .is_red?
  • 53. if just_worked_out and date_tonight take_a_shower end
  • 54. if just_worked_out and date_tonight take_a_shower end if love_mom or just_drunk get_a_tattoo end
  • 55. if just_worked_out and date_tonight take_a_shower end if love_mom or just_drunk get_a_tattoo end if taco_bell? and not pepto_bismol_nearby? get_to_bathroom! end
  • 56. !
  • 57. airlines = [ 'Southwest' , 'United' , 'Delta' ]
  • 58. airlines = [ 'Southwest' , 'United' , 'Delta' ] airlines.reverse => [ 'Delta' , 'United' , 'Southwest' ]
  • 59. airlines = [ 'Southwest' , 'United' , 'Delta' ] airlines.reverse => [ 'Delta' , 'United' , 'Southwest' ] puts airlines => [ 'Southwest' , 'United' , 'Delta' ]
  • 60. airlines = [ 'Southwest' , 'United' , 'Delta' ] airlines.reverse => [ 'Delta' , 'United' , 'Southwest' ] puts airlines => [ 'Southwest' , 'United' , 'Delta' ] airlines.reverse! => [ 'Delta' , 'United' , 'Southwest' ]
  • 61. airlines = [ 'Southwest' , 'United' , 'Delta' ] airlines.reverse => [ 'Delta' , 'United' , 'Southwest' ] puts airlines => [ 'Southwest' , 'United' , 'Delta' ] airlines.reverse! => [ 'Delta' , 'United' , 'Southwest' ] puts airlines => [ 'Delta' , 'United' , 'Southwest' ]
  • 62. everything is an object
  • 64. ‘ Rob’.class => String
  • 65. ‘ Rob’.class => String 42.class
  • 66. ‘ Rob’.class => String 42.class => Fixnum
  • 67. ‘ Rob’.class => String 42.class => Fixnum (23.45).class
  • 68. ‘ Rob’.class => String 42.class => Fixnum (23.45).class => Float
  • 69. ‘ Rob’.class => String 42.class => Fixnum (23.45).class => Float true.class
  • 70. ‘ Rob’.class => String 42.class => Fixnum (23.45).class => Float true.class => TrueClass
  • 71. ‘ Rob’.class => String 42.class => Fixnum (23.45).class => Float true.class => TrueClass nil.class
  • 72. ‘ Rob’.class => String 42.class => Fixnum (23.45).class => Float true.class => TrueClass nil.class => NilClass
  • 73. ‘ Rob’.class => String 42.class => Fixnum (23.45).class => Float true.class => TrueClass nil.class => NilClass String.class
  • 74. ‘ Rob’.class => String 42.class => Fixnum (23.45).class => Float true.class => TrueClass nil.class => NilClass String.class => Class
  • 75. ‘ Rob’.class => String 42.class => Fixnum (23.45).class => Float true.class => TrueClass nil.class => NilClass String.class => Class Class.class
  • 76. ‘ Rob’.class => String 42.class => Fixnum (23.45).class => Float true.class => TrueClass nil.class => NilClass String.class => Class Class.class => Class
  • 77. ‘ Rob’.class => String 42.class => Fixnum (23.45).class => Float true.class => TrueClass nil.class => NilClass String.class => Class Class.class => Class Class.superclass
  • 78. ‘ Rob’.class => String 42.class => Fixnum (23.45).class => Float true.class => TrueClass nil.class => NilClass String.class => Class Class.class => Class Class.superclass => Module
  • 79. ‘ Rob’.class => String 42.class => Fixnum (23.45).class => Float true.class => TrueClass nil.class => NilClass String.class => Class Class.class => Class Class.superclass => Module Module.superclass
  • 80. ‘ Rob’.class => String 42.class => Fixnum (23.45).class => Float true.class => TrueClass nil.class => NilClass String.class => Class Class.class => Class Class.superclass => Module Module.superclass => Object
  • 81. ‘ Rob’.class => String 42.class => Fixnum (23.45).class => Float true.class => TrueClass nil.class => NilClass String.class => Class Class.class => Class Class.superclass => Module Module.superclass => Object Object.superclass
  • 82. ‘ Rob’.class => String 42.class => Fixnum (23.45).class => Float true.class => TrueClass nil.class => NilClass String.class => Class Class.class => Class Class.superclass => Module Module.superclass => Object Object.superclass => BasicObject
  • 83. ‘ Rob’.class => String 42.class => Fixnum (23.45).class => Float true.class => TrueClass nil.class => NilClass String.class => Class Class.class => Class Class.superclass => Module Module.superclass => Object Object.superclass => BasicObject BasicObject.superclass
  • 84. ‘ Rob’.class => String 42.class => Fixnum (23.45).class => Float true.class => TrueClass nil.class => NilClass String.class => Class Class.class => Class Class.superclass => Module Module.superclass => Object Object.superclass => BasicObject BasicObject.superclass => nil
  • 85. Class, Object, Module and all other classes are instances of a class Class . Class, Module and Object have a circular dependency as they are in the core of the OO model
  • 88. 42.methods [:!, :!=, :!~, :%, :&, :*, :**, :+, :+@, :-, :-@, :/, :<, :<<, :<=, :<=>, :==, :===, :=~, :>, :>=, :>>, :[], :^, :__id__, :__send__, :abs, :abs2, :angle, :arg, :between?, :ceil, :chr, :class, :clone, :coerce, :conj, :conjugate, :define_singleton_method, :denominator, :display, :div, :divmod, :downto, :dup, :enum_for, :eql?, :equal?, :even?, :extend, :fdiv, :floor, :freeze, :frozen?, :gcd, :gcdlcm, :hash, :i, :imag, :imaginary, :initialize_clone, :initialize_dup, :inspect, :instance_eval, :instance_exec, :instance_of?, :instance_variable_defined?, :instance_variable_get, :instance_variable_set, :instance_variables, :integer?, :is_a?, :kind_of?, :lcm, :magnitude, :method, :methods, :modulo, :next, :nil?, :nonzero?, :numerator, :object_id, :odd?, :ord, :phase, :polar, :pred, :private_methods, :protected_methods, :public_method, :public_methods, :public_send, :quo, :rationalize, :real, :real?, :rect, :rectangular, :remainder, :respond_to?, :respond_to_missing?, :round, :send, :singleton_class, :singleton_method_added, :singleton_methods, :size, :step, :succ, :taint, :tainted?, :tap, :times, :to_c, :to_enum, :to_f, :to_i, :to_int, :to_r, :to_s, :truncate, :trust, :untaint, :untrust, :untrusted?, :upto, :zero?, :|, :~]
  • 89. 42.methods [:!, :!=, :!~, :%, :&, :*, :**, :+, :+@, :-, :-@, :/, :<, :<<, :<=, :<=>, :==, :===, :=~, :>, :>=, :>>, :[], :^, :__id__, :__send__, :abs, :abs2, :angle, :arg, :between?, :ceil, :chr, :class, :clone, :coerce, :conj, :conjugate, :define_singleton_method, :denominator, :display, :div, :divmod, :downto, :dup, :enum_for, :eql?, :equal?, :even?, :extend, :fdiv, :floor, :freeze, :frozen?, :gcd, :gcdlcm, :hash, :i, :imag, :imaginary, :initialize_clone, :initialize_dup, :inspect, :instance_eval, :instance_exec, :instance_of?, :instance_variable_defined?, :instance_variable_get, :instance_variable_set, :instance_variables , :integer?, :is_a?, :kind_of?, :lcm, :magnitude, :method, :methods, :modulo, :next, :nil?, :nonzero?, :numerator, :object_id, :odd?, :ord, :phase, :polar, :pred, :private_methods , :protected_methods, :public_method, :public_methods , :public_send, :quo, :rationalize, :real, :real?, :rect, :rectangular, :remainder, :respond_to? , :respond_to_missing?, :round, :send , :singleton_class, :singleton_method_added, :singleton_methods, :size, :step, :succ, :taint, :tainted?, :tap, :times, :to_c, :to_enum, :to_f, :to_i, :to_int, :to_r, :to_s, :truncate, :trust, :untaint, :untrust, :untrusted?, :upto, :zero?, :|, :~]
  • 90. var method = 'first_name' eval ( 'person.' + method)
  • 91. var method = 'first_name' eval ( 'person.' + method) method = 'first_name' person.send(method)
  • 92. 2 + 2
  • 93. 2 + 2 2.+(2)
  • 94. 2 + 2 2.+(2) 2.send('+',2)
  • 97. 2 == 2 2.==(2)
  • 98. 2 == 2 2.==(2) 2.send('==',2)
  • 100. car = Vehicle . new ( 'honda' , 'civic' , { :interior => 'beige' }) car = Vehicle . new 'honda' , 'civic' , :interior => 'beige'
  • 102. class Person attr_accessor 'gender' , 'eyes' , 'chin' , 'name' def initialize ( gender,eyes,chin ) @gender = gender @eyes = eyes @chin = chin end end
  • 103. class Person attr_accessor 'gender' , 'eyes' , 'chin' , 'name' def initialize ( gender,eyes,chin ) @gender = gender @eyes = eyes @chin = chin end end rob = Person . new 'male' , 'blue' , 'square'
  • 104. class Person attr_accessor 'gender' , 'eyes' , 'chin' , 'name' def initialize ( gender,eyes,chin ) @gender = gender @eyes = eyes @chin = chin end end rob = Person . new 'male' , 'blue' , 'square' aimee = Person . new 'female' , 'brown' , 'cleft'
  • 105. class Person attr_accessor 'gender' , 'eyes' , 'chin' , 'name' def initialize ( gender,eyes,chin ) @gender = gender @eyes = eyes @chin = chin end end rob = Person . new 'male' , 'blue' , 'square' aimee = Person . new 'female' , 'brown' , 'cleft'
  • 106. class Person def + ( other_person ) gene_pool = [ self ,other_person] Person . new selection(gene_pool, 'gender' ), selection(gene_pool, 'eyes' ), selection(gene_pool, 'chin' ) end def selection ( gene_pool,feature ) return gene_pool[rand(gene_pool.size)].send feature end private 'selection' end
  • 107. baby = rob + aimee
  • 108. baby = rob + aimee baby.name = 'Jack'
  • 109.  
  • 110. baby = rob + aimee baby.name = 'Jack' baby.name=( 'Jack' )
  • 111. baby = rob + aimee baby.name = 'Jack' baby.name=( 'Jack' ) baby.inspect
  • 112. baby = rob + aimee baby.name = 'Jack' baby.name=( 'Jack' ) baby.inspect #<Person:0x0000010083fdf0 @gender=&quot;male&quot;, @eyes=&quot;blue&quot;, @chin=&quot;cleft&quot;, @name=&quot;Jack&quot;>
  • 113. “ When I am working on a problem I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong.” — R. Buckminster Fuller
  • 114. return gene_pool[rand(gene_pool.size)].send feature
  • 115. return gene_pool[rand(gene_pool.size)].send feature class Array def random return self [rand( self .length)] end end
  • 116. return gene_pool[rand(gene_pool.size)].send feature class Array def random return self [rand( self .length)] end end return gene_pool.random.send feature
  • 117. unless []. respond_to ? 'random' class Array def random return self [rand( self .length)] end end end
  • 119. David Heinemeier Hansson (DHH) “ Why Ruby” http://confreaks.net/system/assets/datas/694/original/431-rubyconf2010-keynote-why-ruby-small.mp4?1291226733
  • 120. “ UNIX was not designed to stop its users from doing stupid things, as that would also stop them from doing clever things.” — Doug Gwyn
  • 121. “ There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code.” — Anonymous
  • 122. class Array def random return self [rand( self .length)] end end class Person attr_accessor 'gender' , 'eyes' , 'chin' , 'name' def initialize ( gender,eyes,chin ) @gender = gender @eyes = eyes @chin = chin end def + ( other_person ) gene_pool = [ self ,other_person] Person . new selection(gene_pool, 'gender' ), selection(gene_pool, 'eyes' ), selection(gene_pool, 'chin' ) end def selection ( gene_pool,feature ) return gene_pool.random.send feature end private 'selection' end
  • 123. using System;using System.Collections.Concurrent;using System.Collections.Specialized;using System.ComponentModel.Composition;using System.Diagnostics;using System.IO;using System.IO.Compression;using System.Net;using System.Text.RegularExpressions;using System.Threading;using System.Linq;using Newtonsoft.Json;using NLog;using Raven.Abstractions.Data;using Raven.Abstractions.Exceptions;using Raven.Abstractions.MEF;using Raven.Http.Abstractions;using Raven.Http.Exceptions;using Raven.Http.Extensions;using Formatting = Newtonsoft.Json.Formatting;namespace Raven.Http{ public abstract class HttpServer : IDisposable { private const int MaxConcurrentRequests = 192; protected readonly IResourceStore DefaultResourceStore; protected readonly IRavenHttpConfiguration DefaultConfiguration; private readonly ThreadLocal<string> currentTenantId = new ThreadLocal<string>(); private readonly ThreadLocal<IResourceStore> currentDatabase = new ThreadLocal<IResourceStore>(); private readonly ThreadLocal<IRavenHttpConfiguration> currentConfiguration = new ThreadLocal<IRavenHttpConfiguration>(); protected readonly ConcurrentDictionary<string, IResourceStore> ResourcesStoresCache = new ConcurrentDictionary<string, IResourceStore>(StringComparer.InvariantCultureIgnoreCase); private readonly ConcurrentDictionary<string, DateTime> databaseLastRecentlyUsed = new ConcurrentDictionary<string, DateTime>();
  • 124. public int NumberOfRequests { get { return Thread.VolatileRead(ref physicalRequestsCount); } } [ImportMany] public OrderedPartCollection<AbstractRequestResponder> RequestResponders { get; set; } public IRavenHttpConfiguration Configuration { get { return DefaultConfiguration; } } public abstract Regex TenantsQuery { get; } private HttpListener listener; private static readonly Logger logger = LogManager.GetCurrentClassLogger(); private int reqNum; // concurrent requests // we set 1/4 aside for handling background tasks private readonly SemaphoreSlim concurretRequestSemaphore = new SemaphoreSlim(MaxConcurrentRequests); private Timer databasesCleanupTimer; private int physicalRequestsCount; public bool HasPendingRequests { get { return concurretRequestSemaphore.CurrentCount != MaxConcurrentRequests; } } protected HttpServer(IRavenHttpConfiguration configuration, IResourceStore resourceStore) {
  • 125. DefaultResourceStore = resourceStore; DefaultConfiguration = configuration; configuration.Container.SatisfyImportsOnce(this); foreach (var requestResponder in RequestResponders) { requestResponder.Value.Initialize(() => currentDatabase.Value, () => currentConfiguration.Value, () => currentTenantId.Value, this); } } #region IDisposable Members public void Dispose() { databasesCleanupTimer.Dispose(); if (listener != null && listener.IsListening) listener.Stop(); foreach (var documentDatabase in ResourcesStoresCache) { documentDatabase.Value.Dispose(); } } #endregion public void Start() { listener = new HttpListener(); string virtualDirectory = DefaultConfiguration.VirtualDirectory; if (virtualDirectory.EndsWith(&quot;/&quot;) == false) virtualDirectory = virtualDirectory + &quot;/&quot;; listener.Prefixes.Add(&quot;http://&quot; + (DefaultConfiguration.HostName ?? &quot;+&quot;) + &quot;:&quot; + DefaultConfiguration.Port + virtualDirectory);
  • 126. switch (DefaultConfiguration.AnonymousUserAccessMode) { case AnonymousUserAccessMode.None: listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication; break; case AnonymousUserAccessMode.All: listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication | AuthenticationSchemes.Anonymous; listener.AuthenticationSchemeSelectorDelegate = request => { if(request.RawUrl.StartsWith(&quot;/admin&quot;,StringComparison.InvariantCultureIgnoreCase)) return AuthenticationSchemes.IntegratedWindowsAuthentication; return AuthenticationSchemes.Anonymous; }; break; case AnonymousUserAccessMode.Get: listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication | AuthenticationSchemes.Anonymous; listener.AuthenticationSchemeSelectorDelegate = request => { return IsGetRequest(request.HttpMethod, request.Url.AbsolutePath) ? AuthenticationSchemes.Anonymous | AuthenticationSchemes.IntegratedWindowsAuthentication : AuthenticationSchemes.IntegratedWindowsAuthentication; }; break; default: throw new ArgumentException(&quot;Cannot understand access mode: &quot; + DefaultConfiguration.AnonymousUserAccessMode); } databasesCleanupTimer = new Timer(CleanupDatabases, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1)); listener.Start(); listener.BeginGetContext(GetContext, null); }
  • 127. private void CleanupDatabases(object state) { var databasesToCleanup = databaseLastRecentlyUsed .Where(x=>(DateTime.Now - x.Value).TotalMinutes > 10) .Select(x=>x.Key) .ToArray(); foreach (var db in databasesToCleanup) { DateTime _; databaseLastRecentlyUsed.TryRemove(db, out _); IResourceStore database; if(ResourcesStoresCache.TryRemove(db, out database)) database.Dispose(); } } private void GetContext(IAsyncResult ar) { IHttpContext ctx; try { ctx = new HttpListenerContextAdpater(listener.EndGetContext(ar), DefaultConfiguration); //setup waiting for the next request listener.BeginGetContext(GetContext, null); } catch (InvalidOperationException) { // can't get current request / end new one, probably // listner shutdown return; } catch (HttpListenerException) { // can't get current request / end new one, probably // listner shutdown return; }
  • 128. if (concurretRequestSemaphore.Wait(TimeSpan.FromSeconds(5)) == false) { HandleTooBusyError(ctx); return; } try { Interlocked.Increment(ref physicalRequestsCount); HandleActualRequest(ctx); } finally { concurretRequestSemaphore.Release(); } } public void HandleActualRequest(IHttpContext ctx) { var sw = Stopwatch.StartNew(); bool ravenUiRequest = false; try { ravenUiRequest = DispatchRequest(ctx); } catch (Exception e) { HandleException(ctx, e); if (ShouldLogException(e)) logger.WarnException(&quot;Error on request&quot;, e); } finally { try { FinalizeRequestProcessing(ctx, sw, ravenUiRequest); } catch (Exception e) { logger.ErrorException(&quot;Could not finalize request properly&quot;, e); }
  • 129. protected virtual bool ShouldLogException(Exception exception) { return true; } private void FinalizeRequestProcessing(IHttpContext ctx, Stopwatch sw, bool ravenUiRequest) { LogHttpRequestStatsParams logHttpRequestStatsParam = null; try { logHttpRequestStatsParam = new LogHttpRequestStatsParams( sw, ctx.Request.Headers, ctx.Request.HttpMethod, ctx.Response.StatusCode, ctx.Request.Url.PathAndQuery); } catch (Exception e) { logger.WarnException(&quot;Could not gather information to log request stats&quot;, e); } ctx.FinalizeResonse(); sw.Stop(); if (ravenUiRequest || logHttpRequestStatsParam == null) return; LogHttpRequestStats(logHttpRequestStatsParam); ctx.OutputSavedLogItems(logger); } private void LogHttpRequestStats(LogHttpRequestStatsParams logHttpRequestStatsParams) { // we filter out requests for the UI because they fill the log with information // we probably don't care about them anyway. That said, we do output them if they take too // long.
  • 130. if (logHttpRequestStatsParams.Headers[&quot;Raven-Timer-Request&quot;] == &quot;true&quot; && logHttpRequestStatsParams.Stopwatch.ElapsedMilliseconds <= 25) return; var curReq = Interlocked.Increment(ref reqNum); logger.Debug(&quot;Request #{0,4:#,0}: {1,-7} - {2,5:#,0} ms - {5,-10} - {3} - {4}&quot;, curReq, logHttpRequestStatsParams.HttpMethod, logHttpRequestStatsParams.Stopwatch.ElapsedMilliseconds, logHttpRequestStatsParams.ResponseStatusCode, logHttpRequestStatsParams.RequestUri, currentTenantId.Value); } private void HandleException(IHttpContext ctx, Exception e) { try { if (e is BadRequestException) HandleBadRequest(ctx, (BadRequestException)e); else if (e is ConcurrencyException) HandleConcurrencyException(ctx, (ConcurrencyException)e); else if (TryHandleException(ctx, e)) return; else HandleGenericException(ctx, e); } catch (Exception) { logger.ErrorException(&quot;Failed to properly handle error, further error handling is ignored&quot;, e); } } protected abstract bool TryHandleException(IHttpContext ctx, Exception exception);
  • 131. private static void HandleTooBusyError(IHttpContext ctx) { ctx.Response.StatusCode = 503; ctx.Response.StatusDescription = &quot;Service Unavailable&quot;; SerializeError(ctx, new { Url = ctx.Request.RawUrl, Error = &quot;The server is too busy, could not acquire transactional access&quot; }); } private static void HandleGenericException(IHttpContext ctx, Exception e) { ctx.Response.StatusCode = 500; ctx.Response.StatusDescription = &quot;Internal Server Error&quot;; SerializeError(ctx, new { Url = ctx.Request.RawUrl, Error = e.ToString() }); } private static void HandleBadRequest(IHttpContext ctx, BadRequestException e) { ctx.SetStatusToBadRequest(); SerializeError(ctx, new { Url = ctx.Request.RawUrl, e.Message, Error = e.Message }); }
  • 132. private static void HandleConcurrencyException(IHttpContext ctx, ConcurrencyException e) { ctx.Response.StatusCode = 409; ctx.Response.StatusDescription = &quot;Conflict&quot;; SerializeError(ctx, new { Url = ctx.Request.RawUrl, e.ActualETag, e.ExpectedETag, Error = e.Message }); } protected static void SerializeError(IHttpContext ctx, object error) { var sw = new StreamWriter(ctx.Response.OutputStream); new JsonSerializer().Serialize(new JsonTextWriter(sw) { Formatting = Formatting.Indented, }, error); sw.Flush(); } private bool DispatchRequest(IHttpContext ctx) { if (AssertSecurityRights(ctx) == false) return false; SetupRequestToProperDatabase(ctx); CurrentOperationContext.Headers.Value = ctx.Request.Headers; try { OnDispatchingRequest(ctx); if (DefaultConfiguration.HttpCompression) AddHttpCompressionIfClientCanAcceptIt(ctx);
  • 133. AddAccessControlAllowOriginHeader(ctx); foreach (var requestResponderLazy in RequestResponders) { var requestResponder = requestResponderLazy.Value; if (requestResponder.WillRespond(ctx)) { requestResponder.Respond(ctx); return requestResponder.IsUserInterfaceRequest; } } ctx.SetStatusToBadRequest(); if (ctx.Request.HttpMethod == &quot;HEAD&quot;) return false; ctx.Write( @&quot;<html> <body> <h1>Could not figure out what to do</h1> <p>Your request didn't match anything that Raven knows to do, sorry...</p> </body></html>&quot;); } finally { CurrentOperationContext.Headers.Value = new NameValueCollection(); currentDatabase.Value = DefaultResourceStore; currentConfiguration.Value = DefaultConfiguration; } return false; } protected virtual void OnDispatchingRequest(IHttpContext ctx){}
  • 134. private void SetupRequestToProperDatabase(IHttpContext ctx) { var requestUrl = ctx.GetRequestUrlForTenantSelection(); var match = TenantsQuery.Match(requestUrl); if (match.Success == false) { currentTenantId.Value = Constants.DefaultDatabase; currentDatabase.Value = DefaultResourceStore; currentConfiguration.Value = DefaultConfiguration; } else { var tenantId = match.Groups[1].Value; IResourceStore resourceStore; if(TryGetOrCreateResourceStore(tenantId, out resourceStore)) { databaseLastRecentlyUsed.AddOrUpdate(tenantId, DateTime.Now, (s, time) => DateTime.Now); if (string.IsNullOrEmpty(Configuration.VirtualDirectory) == false && Configuration.VirtualDirectory != &quot;/&quot;) { ctx.AdjustUrl(Configuration.VirtualDirectory + match.Value); } else { ctx.AdjustUrl(match.Value); } currentTenantId.Value = tenantId; currentDatabase.Value = resourceStore; currentConfiguration.Value = resourceStore.Configuration; } else { throw new BadRequestException(&quot;Could not find a database named: &quot; + tenantId); } } }
  • 135. protected abstract bool TryGetOrCreateResourceStore(string name, out IResourceStore database); private void AddAccessControlAllowOriginHeader(IHttpContext ctx) { if (string.IsNullOrEmpty(DefaultConfiguration.AccessControlAllowOrigin)) return; ctx.Response.AddHeader(&quot;Access-Control-Allow-Origin&quot;, DefaultConfiguration.AccessControlAllowOrigin); } private static void AddHttpCompressionIfClientCanAcceptIt(IHttpContext ctx) { var acceptEncoding = ctx.Request.Headers[&quot;Accept-Encoding&quot;]; if (string.IsNullOrEmpty(acceptEncoding)) return; // gzip must be first, because chrome has an issue accepting deflate data // when sending it json text if ((acceptEncoding.IndexOf(&quot;gzip&quot;, StringComparison.InvariantCultureIgnoreCase) != -1)) { ctx.SetResponseFilter(s => new GZipStream(s, CompressionMode.Compress, true)); ctx.Response.AddHeader(&quot;Content-Encoding&quot;,&quot;gzip&quot;); } else if (acceptEncoding.IndexOf(&quot;deflate&quot;, StringComparison.InvariantCultureIgnoreCase) != -1) { ctx.SetResponseFilter(s => new DeflateStream(s, CompressionMode.Compress, true)); ctx.Response.AddHeader(&quot;Content-Encoding&quot;, &quot;deflate&quot;); } } private bool AssertSecurityRights(IHttpContext ctx) { if (DefaultConfiguration.AnonymousUserAccessMode == AnonymousUserAccessMode.None && IsInvalidUser(ctx)) { ctx.SetStatusToUnauthorized(); return false; }
  • 136. IHttpRequest httpRequest = ctx.Request; if (DefaultConfiguration.AnonymousUserAccessMode == AnonymousUserAccessMode.Get && IsInvalidUser(ctx) && IsGetRequest(httpRequest.HttpMethod, httpRequest.Url.AbsolutePath) == false ) { ctx.SetStatusToUnauthorized(); return false; } return true; } protected virtual bool IsGetRequest(string httpMethod, string requestPath) { return (httpMethod == &quot;GET&quot; || httpMethod == &quot;HEAD&quot;); } private static bool IsInvalidUser(IHttpContext ctx) { return (ctx.User == null || ctx.User.Identity == null || ctx.User.Identity.IsAuthenticated == false); } public void ResetNumberOfRequests() { Interlocked.Exchange(ref reqNum, 0); Interlocked.Exchange(ref physicalRequestsCount, 0); } }} 517 lines of code
  • 137. webserver = TCPServer . new ( '127.0.0.1' , 3000 ) while (session = webserver.accept) session.print &quot;HTTP/1.1 200/OK Content-type:text/html &quot; request = session.gets filename = request.match( / (.*?) / )[ 1 ] filename = 'index.html' if filename == '' begin session.print File .read(filename) rescue Errno :: ENOENT session.print 'File not found' end session.close end
  • 138. “ There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies and the other way is to make it so complicated that there are no obvious deficiencies.” — C.A.R. Hoare
  • 139. class Person def + ( other_person ) gene_pool = [ self ,other_person] Person . new selection(gene_pool, 'gender' ), selection(gene_pool, 'eyes' ), selection(gene_pool, 'chin' ) end def selection ( gene_pool,feature ) return gene_pool[rand(gene_pool.size)].send feature end private 'selection' end
  • 140. class Person def + ( other_person ) gene_pool = [ self ,other_person] Person . new selection(gene_pool, 'gender' ), selection(gene_pool, 'eyes' ), selection(gene_pool, 'chin' ) end def selection ( gene_pool,feature ) return gene_pool[rand(gene_pool.size)].send feature end private 'selection' end
  • 141. class Person def + ( other_person ) gene_pool = [ self ,other_person] Person . new selection(gene_pool, 'gender' ), selection(gene_pool, 'eyes' ), selection(gene_pool, 'chin' ) end def selection ( gene_pool,feature ) return gene_pool[rand(gene_pool.size)].send feature end private 'selection' end
  • 142. Implicit return Any statement in Ruby returns the value of the last evaluated expression
  • 143. ruby-1.9.2 :001 > puts 'Hello, world!'
  • 144. ruby-1.9.2 :001 > puts 'Hello, world!'Hello, world! => nil ruby-1.9.2 :002 >
  • 145. ruby-1.9.2 :001 > puts 'Hello, world!'Hello, world! => nil ruby-1.9.2 :002 > puts('Hello, world!')
  • 146. ruby-1.9.2 :001 > puts 'Hello, world!'Hello, world! => nil ruby-1.9.2 :002 > puts('Hello, world!')Hello, world! => nil ruby-1.9.2 :003 >
  • 147. Blabber Talk to your servers via IM
  • 148.  
  • 149. gems
  • 150. rob$
  • 152. rob$ gem install rails rob$ gem install httparty json
  • 153. require 'rubygems' require 'json' require 'httparty'
  • 155. rob$ irbruby-1.9.2 :001 > HTTParty
  • 156. rob$ irbruby-1.9.2 :001 > HTTPartyNameError: uninitialized constant Object::HTTParty from (irb):1 from /Users/rob/.rvm/rubies/ruby-1.9.2-p180/bin/irb:16:in `<main>'ruby-1.9.2 :002 >
  • 157. rob$ irbruby-1.9.2 :001 > HTTPartyNameError: uninitialized constant Object::HTTParty from (irb):1 from /Users/rob/.rvm/rubies/ruby-1.9.2-p180/bin/irb:16:in `<main>'ruby-1.9.2 :002 > require 'httparty'
  • 158. rob$ irbruby-1.9.2 :001 > HTTPartyNameError: uninitialized constant Object::HTTParty from (irb):1 from /Users/rob/.rvm/rubies/ruby-1.9.2-p180/bin/irb:16:in `<main>'ruby-1.9.2 :002 > require 'httparty' => true ruby-1.9.2 :003 >
  • 159. rob$ irbruby-1.9.2 :001 > HTTPartyNameError: uninitialized constant Object::HTTParty from (irb):1 from /Users/rob/.rvm/rubies/ruby-1.9.2-p180/bin/irb:16:in `<main>'ruby-1.9.2 :002 > require 'httparty' => true ruby-1.9.2 :003 > HTTParty
  • 160. rob$ irbruby-1.9.2 :001 > HTTPartyNameError: uninitialized constant Object::HTTParty from (irb):1 from /Users/rob/.rvm/rubies/ruby-1.9.2-p180/bin/irb:16:in `<main>'ruby-1.9.2 :002 > require 'httparty' => true ruby-1.9.2 :003 > HTTParty => HTTParty ruby-1.9.2 :004 >
  • 163. Command line interface to the Active.com Search API
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 171. What you need to know
  • 172. Required Gems require 'json' require 'httparty'
  • 173. Search API Endpoint http://api.amp.active.com/search? v=json& k=keywords& m=meta:channel%3DRunning& api_key=wuhmn9ye94xn3xnteudxsavw
  • 175. Parse JSON JSON.parse(text) HTTP call HTTParty.get(url)
  • 176. Get user input user_input = gets
  • 177. Get user input user_input = gets Remove newlines user_input.chomp
  • 178. Get user input user_input = gets Print to STDOUT print 'text'puts 'text' Remove newlines user_input.chomp
  • 179. Iterate through array with index my_array.each_with_index do |item,i| puts “#{item} is at position #{i}” end
  • 180. Exit exit 0 Iterate through array with index my_array.each_with_index do |item,i| puts “#{item} is at position #{i}” end
  • 181.
  • 183. require 'json' require 'httparty' HTTParty.get(url) JSON.parse(text) user_input = gets print 'text' puts 'text' user_input.chomp my_array.each_with_index do |item,i| puts “#{item} is as position #{i}” end http://api.amp.active.com/search? v=json& k=keywords& m=meta:channel%3DRunning& api_key= wuhmn9ye94xn3xnteudxsavw exit 0
  • 184. “ I am rarely happier than when spending an entire day programming my computer to perform automatically a task that would otherwise take me a good ten seconds to do by hand.” — Douglas Adams
  • 185. Learning a new language
  • 186.  
  • 187.  
  • 188. EGO
  • 189. “ Would you rather be a king of fools or a student of masters?”