SlideShare una empresa de Scribd logo
1 de 93
Descargar para leer sin conexión
Ruby and Cocoa
 Facilitate development on OSX
About me
About me
Rapperswil
http://www.flickr.com/photos/turtlemom_nancy/4026208166/sizes/l/
huesler informatik
huesler informatik

upstream agile
huesler informatik

upstream agile

co-up.de
Ruby and Cocoa
Ruby
passionate
  http://www.flickr.com/photos/gi/378823/sizes/o/
Apple OSX
passionate
  http://www.flickr.com/photos/gi/378823/sizes/o/
Landscape
 http://www.flickr.com/photos/kiumo/4203883504/sizes/o/
Cocoa
http://www.flickr.com/photos/luder5/4100921399/sizes/l/
Cocoa
Cocoa
•   Core Foundation
Cocoa
•   Core Foundation
•   Appkit
Cocoa
•   Core Foundation
•   Appkit
•   Core * (Audio/Video/Image/Data
    etc.)
Cocoa
•   Core Foundation
•   Appkit
•   Core * (Audio/Video/Image/Data
    etc.)
•   Scripting bridge
Cocoa
•   Core Foundation
•   Appkit
•   Core * (Audio/Video/Image/Data
    etc.)
•   Scripting bridge
•   others
Interface Builder
XCode
Objective-C
NSMutableArray *anArray = [
      [NSMutableArray alloc]   init
    ];
[anArray addObject:@"Element   1"];
[anArray addObject:@"Element   2"];
[anArray addObject:@"Element   3"];

//Use a for each loop to iterate
through the array
for (NSString *s in anArray) {
     NSLog(s);
}
//Release the array
[anArray release]
Ruby And Cocoa
Ruby Cocoa
HotCocoa
picture shamelessly cropped from http://www.slideshare.net/mattetti/macruby-hotcocoa-presentation-by-rich-kilmer
Scripting Bridge
    http://www.flickr.com/photos/bensonkua/2851908095/sizes/l/
Good to know
Good to know
•   Available commands for each
    application are in a .sdef file
Good to know
•   Available commands for each
    application are in a .sdef file
•   Terminal.app/Contents/Resources/
    Terminal.sdef
Good to know
•   Available commands for each
    application are in a .sdef file
•   Terminal.app/Contents/Resources/
    Terminal.sdef
•   gem rb-appscript (native extension
    so not for MacRuby)
1 <command name="do script" code="coredosc"
 2     description="Runs a UNIX shell script or command.">
 3     <cocoa class="TTDoScriptCommand"/>
 4     <direct-parameter type="text"
 5         description="The command to execute." optional="yes"/>
 6     <parameter name="with command"
 7         description="Data to be passed to the Terminal..."
 8         code="cmnd" optional="yes" hidden="yes">
 9         <cocoa key="Command" />
10         <type type="text" />
11         <type type="any" /> <!-- support null case -->
12     </parameter>
13     <parameter name="in"
14         description="The tab in which to execute the command"
15         code="kfil" optional="yes">
16         <cocoa key="Target" />
17         <type type="tab" />
18         <type type="window" />
19         <type type="any" /> <!-- support null case -->
20     </parameter>
21     <result type="tab"
22         description="The tab the command was executed in." />
23 </command>
24
Control Terminal
1 #!/usr/bin/env ruby
    2 require 'rubygems'
    3 require 'appscript'
    4 include Appscript
    5
    6 terminal = app('Terminal')
    7 current_window = terminal.windows.first
    8 current_tab = current_window.tabs.last
    9 process = app("System
Events").application_processes[
   10   "Terminal.app"
   11   ]
   12
   13 process.keystroke('t', :using => :command_down)
   14 terminal.do_script('top', :in => current_tab)
1 #!/usr/bin/env ruby
    2 require 'rubygems'
    3 require 'appscript'
    4 include Appscript
    5
    6 terminal = app('Terminal')
    7 current_window = terminal.windows.first
    8 current_tab = current_window.tabs.last
    9 process = app("System
Events").application_processes[
   10   "Terminal.app"
   11   ]
   12
   13 process.keystroke('t', :using => :command_down)
   14 terminal.do_script('top', :in => current_tab)
1 #!/usr/bin/env ruby
    2 require 'rubygems'
    3 require 'appscript'
    4 include Appscript
    5
    6 terminal = app('Terminal')
    7 current_window = terminal.windows.first
    8 current_tab = current_window.tabs.last
    9 process = app("System
Events").application_processes[
   10   "Terminal.app"
   11   ]
   12
   13 process.keystroke('t', :using => :command_down)
   14 terminal.do_script('top', :in => current_tab)
7 current_window = terminal.windows.first
    8 current_tab = current_window.tabs.last
    9 process = app("System
Events").application_processes[
   10   "Terminal.app"
   11   ]
   12
   13 process.keystroke('t', :using => :command_down)
   14 terminal.do_script('top', :in => current_tab)
Problems with MacRuby
Problems with MacRuby
Problems with MacRuby

•   Some methods don’t seem to be
    available
iTunes
1 #!/usr/bin/env macruby
    2
    3 framework 'ScriptingBridge'
    4
    5 itunes =
SBApplication.applicationWithBundleIdentifier(
    6   "com.apple.iTunes"
    7 )
    8 library = itunes.sources.objectWithName
("Library")
    9
   10 library.userPlaylists.each do |playlist|
   11   puts playlist.name
   12 end
2
    3 framework 'ScriptingBridge'
    4
    5 itunes =
SBApplication.applicationWithBundleIdentifier(
    6   "com.apple.iTunes"
    7 )
    8 library = itunes.sources.objectWithName
("Library")
    9
   10 library.userPlaylists.each do |playlist|
   11   puts playlist.name
   12 end
2
    3 framework 'ScriptingBridge'
    4
    5 itunes =
SBApplication.applicationWithBundleIdentifier(
    6   "com.apple.iTunes"
    7 )
    8 library = itunes.sources.objectWithName
("Library")
    9
   10 library.userPlaylists.each do |playlist|
   11   puts playlist.name
   12 end
Core Location
1   #!/usr/bin/env macruby
 2   framework 'CoreLocation'
 3
 4   loc = CLLocationManager.alloc.init
 5   loc.delegate = self
 6   loc.startUpdatingLocation
 7
 8   # keep the script running
 9   NSRunLoop.currentRunLoop.runUntilDate(
10     NSDate.distantFuture
11   )
1   #!/usr/bin/env macruby
 2   framework 'CoreLocation'
 3
 4   loc = CLLocationManager.alloc.init
 5   loc.delegate = self
 6   loc.startUpdatingLocation
 7
 8   # keep the script running
 9   NSRunLoop.currentRunLoop.runUntilDate(
10     NSDate.distantFuture
11   )
1 def locationManager(
2         manager,
3         didUpdateToLocation: new_location,
4         fromLocation: old_location
5   )
6
7   puts "loc: #{new_location.description}"
8 end
2   framework 'CoreLocation'
 3
 4   loc = CLLocationManager.alloc.init
 5   loc.delegate = self
 6   loc.startUpdatingLocation
 7
 8   # keep the script running
 9   NSRunLoop.currentRunLoop.runUntilDate(
10     NSDate.distantFuture
11   )
1   #!/usr/bin/env macruby
 2   framework 'CoreLocation'
 3
 4   def locationManager(manager,
 5                        didUpdateToLocation: new_location,
 6                        fromLocation: old_location
 7                      )
 8     puts "location: #{new_location.description}"
 9   end
10
11   loc = CLLocationManager.alloc.init
12   loc.delegate = self
13   loc.startUpdatingLocation
14
15   # keep the script running
16   NSRunLoop.currentRunLoop.runUntilDate(
17     NSDate.distantFuture
18   )
Grand Central
  Dispatch
Grand Central Dispatch
Grand Central Dispatch
•   MacRuby only
Grand Central Dispatch
•   MacRuby only
•   Synchronous
Grand Central Dispatch
•   MacRuby only
•   Synchronous
•   Asynchronous
Grand Central Dispatch
•   MacRuby only
•   Synchronous
•   Asynchronous
•   Parallel
Grand Central Dispatch
•   MacRuby only
•   Synchronous
•   Asynchronous
•   Parallel
•   Synchronization
Asynchronous
1   #!/usr/bin/env macruby
 2
 3   queue = Dispatch::Queue.new(
 4       'ch.huesler-informatik.scotrubyconf.gcd'
 5     )
 6
 7   queue.async do
 8     puts 'Starting asyn. NONE BLOCKING!'
 9     sleep 2.00
10     puts "Finished asyn"
11   end
12   puts "code not being blocked"
13
14   NSRunLoop.currentRunLoop.runUntilDate(
15       NSDate.distantFuture
16     )
17
1   #!/usr/bin/env macruby
 2
 3   queue = Dispatch::Queue.new(
 4       'ch.huesler-informatik.scotrubyconf.gcd'
 5     )
 6
 7   queue.async do
 8     puts 'Starting asyn. NONE BLOCKING!'
 9     sleep 2.00
10     puts "Finished asyn"
11   end
12   puts "code not being blocked"
13
14   NSRunLoop.currentRunLoop.runUntilDate(
15       NSDate.distantFuture
16     )
17
7   queue.async do
 8     puts 'Starting asyn. NONE BLOCKING!'
 9     sleep 2.00
10     puts "Finished asyn"
11   end
12   puts "code not being blocked"
13
14   NSRunLoop.currentRunLoop.runUntilDate(
15       NSDate.distantFuture
16     )
17
Synchronous
1   #!/usr/bin/env macruby
 2
 3   queue = Dispatch::Queue.new(
 4       'ch.huesler-informatik.scotrubyconf.gcd'
 5     )
 6
 7   queue.sync do
 8     puts 'Starting sync. BLOCKING!'
 9     sleep 3.0
10     puts 'Finished sync'
11   end
12   puts "code being blocked"
13
14   NSRunLoop.currentRunLoop.runUntilDate(
15       NSDate.distantFuture
16     )
17
Synchronized
1   #!/usr/bin/env macruby
 2
 3   worker_queue = Dispatch::Queue.new(
 4       'ch.huesler-informatik.scotrubyconf.gcd'
 5     )
 6   group = Dispatch::Group.new
 7
 8   0.upto(10) do |i|
 9     puts "Dispatch #{i} to GCD"
10     worker_queue.async(group) do
11       puts "working on #{i}"
12     end
13   end
14   puts "waiting for gcd"
15   group.wait
16   puts "done"
17
1   #!/usr/bin/env macruby
 2
 3   worker_queue = Dispatch::Queue.new(
 4       'ch.huesler-informatik.scotrubyconf.gcd'
 5     )
 6   group = Dispatch::Group.new
 7
 8   0.upto(10) do |i|
 9     puts "Dispatch #{i} to GCD"
10     worker_queue.async(group) do
11       puts "working on #{i}"
12     end
13   end
14   puts "waiting for gcd"
15   group.wait
16   puts "done"
17
7
 8   0.upto(10) do |i|
 9     puts "Dispatch #{i} to GCD"
10     worker_queue.async(group) do
11       puts "working on #{i}"
12     end
13   end
14   puts "waiting for gcd"
15   group.wait
16   puts "done"
17
Concurrent
1   #!/usr/bin/env macruby
 2
 3   group = Dispatch::Group.new
 4   result = []
 5   1.upto(10).each do |i|
 6     Dispatch::Queue.concurrent.async(group) do
 7       sleep 2
 8       result << i
 9     end
10   end
11   group.wait
12   puts result.inspect
.plist files
1 #!/usr/bin/env ruby
    2 require "osx/cocoa"
    3 include OSX
    4
    5 file_name = 'Info.plist'
    6 plist =
NSDictionary.dictionaryWithContentsOfFile(
    7            file_name
    8          )
    9
   10 plist['CFBundleVersion'] = '2.0.1'
   11
   12 plist.writeToFile_atomically(
   13     file_name,
   14     true
   15   )
1 #!/usr/bin/env ruby
    2 require "osx/cocoa"
    3 include OSX
    4
    5 file_name = 'Info.plist'
    6 plist =
NSDictionary.dictionaryWithContentsOfFile(
    7            file_name
    8          )
    9
   10 plist['CFBundleVersion'] = '2.0.1'
   11
   12 plist.writeToFile_atomically(
   13     file_name,
   14     true
   15   )
3 include OSX
    4
    5 file_name = 'Info.plist'
    6 plist =
NSDictionary.dictionaryWithContentsOfFile(
    7            file_name
    8          )
    9
   10 plist['CFBundleVersion'] = '2.0.1'
   11
   12 plist.writeToFile_atomically(
   13     file_name,
   14     true
   15   )
Keychain
 Access
Details
Details
•   MacRuby has issues with void
    pointer (patch pending)
Details
•   MacRuby has issues with void
    pointer (patch pending)
•   Use objective c wrapper instead
    (dynlib or bundle)
Details
•   MacRuby has issues with void
    pointer (patch pending)
•   Use objective c wrapper instead
    (dynlib or bundle)
•   Generate metadata to make it
    work
Details
•   MacRuby has issues with void
    pointer (patch pending)
•   Use objective c wrapper instead
    (dynlib or bundle)
•   Generate metadata to make it
    work
1 export FILE_PATH = ~/Library/BridgeSupport
    2 export FRAMEWORK_PATH = ~/Library/BridgeSupport/
Security.bridgesupport
    3 mkdir $FILE_PATH
    4 gen_bridge_metadata -f Security -o $FRAMEWORK_PATH
1   require 'osx/cocoa'
 2   include OSX
 3   require_framework 'Security'
 4
 5   # Set up some relevant variables
 6
 7   service = "ch.huesler-informatik.scotrubyconf.keychain"
 8   account = "Highlander"
 9   original_password = "Rrrueby"
10
11   # Add password
12   SecKeychainAddGenericPassword(
13       nil,
14       service.length,
15       service,
16       account.length,
17       account,
18       original_password.length,
19       original_password,
20       nil
21   )
1   require 'osx/cocoa'
 2   include OSX
 3   require_framework 'Security'
 4
 5   # Set up some relevant variables
 6
 7   service = "ch.huesler-informatik.scotrubyconf.keychain"
 8   account = "Highlander"
 9   original_password = "Rrrueby"
10
11   # Add password
12   SecKeychainAddGenericPassword(
13       nil,
14       service.length,
15       service,
16       account.length,
17       account,
18       original_password.length,
19       original_password,
20       nil
21   )
1 # Add password
 2 SecKeychainAddGenericPassword(
 3     nil,
 4     service.length,
 5     service,
 6     account.length,
 7     account,
 8     original_password.length,
 9     original_password,
10     nil
11 )
1 # Query   the keychain
2 status,   *password = SecKeychainFindGenericPassword(
3           nil,
4           service.length,
5           service,
6           account.length,
7           account
8       )
1   # Password-related data. Shifting pointers
2   length = password.shift
3   data = password.shift
4   plain_password = data.bytestr(length)
5
6   puts "Password: #{plain_password}"
That’s all!
Questions?

Más contenido relacionado

La actualidad más candente

Всеволод Струкчинский: Node.js
Всеволод Струкчинский: Node.jsВсеволод Струкчинский: Node.js
Всеволод Струкчинский: Node.js
Yandex
 

La actualidad más candente (20)

Всеволод Струкчинский: Node.js
Всеволод Струкчинский: Node.jsВсеволод Струкчинский: Node.js
Всеволод Струкчинский: Node.js
 
Adventures in infrastructure as code
Adventures in infrastructure as codeAdventures in infrastructure as code
Adventures in infrastructure as code
 
Speed up web APIs with Expressive and Swoole (PHP Day 2018)
Speed up web APIs with Expressive and Swoole (PHP Day 2018) Speed up web APIs with Expressive and Swoole (PHP Day 2018)
Speed up web APIs with Expressive and Swoole (PHP Day 2018)
 
YASPS OPENNING
YASPS OPENNINGYASPS OPENNING
YASPS OPENNING
 
Better detection of what modules are used by some Perl 5 code
Better detection of what modules are used by some Perl 5 codeBetter detection of what modules are used by some Perl 5 code
Better detection of what modules are used by some Perl 5 code
 
Release with confidence
Release with confidenceRelease with confidence
Release with confidence
 
PL/Perl - New Features in PostgreSQL 9.0 201012
PL/Perl - New Features in PostgreSQL 9.0 201012PL/Perl - New Features in PostgreSQL 9.0 201012
PL/Perl - New Features in PostgreSQL 9.0 201012
 
How to inspect a RUNNING perl process
How to inspect a RUNNING perl processHow to inspect a RUNNING perl process
How to inspect a RUNNING perl process
 
SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)
 
Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)
 
DevOpsCon 2021: Go Web Development 101
DevOpsCon 2021: Go Web Development 101DevOpsCon 2021: Go Web Development 101
DevOpsCon 2021: Go Web Development 101
 
entwickler.de Go Day: Go Web Development 101
entwickler.de Go Day: Go Web Development 101entwickler.de Go Day: Go Web Development 101
entwickler.de Go Day: Go Web Development 101
 
betterCode() Go: Einstieg in Go, Standard-Library und Ökosystem
betterCode() Go: Einstieg in Go, Standard-Library und ÖkosystembetterCode() Go: Einstieg in Go, Standard-Library und Ökosystem
betterCode() Go: Einstieg in Go, Standard-Library und Ökosystem
 
DevOps in PHP environment
DevOps in PHP environmentDevOps in PHP environment
DevOps in PHP environment
 
Shell Script
Shell ScriptShell Script
Shell Script
 
What you need to remember when you upload to CPAN
What you need to remember when you upload to CPANWhat you need to remember when you upload to CPAN
What you need to remember when you upload to CPAN
 
Asynchronous PHP and Real-time Messaging
Asynchronous PHP and Real-time MessagingAsynchronous PHP and Real-time Messaging
Asynchronous PHP and Real-time Messaging
 
Php assíncrono com_react_php
Php assíncrono com_react_phpPhp assíncrono com_react_php
Php assíncrono com_react_php
 
Anyevent
AnyeventAnyevent
Anyevent
 
Perl: Coro asynchronous
Perl: Coro asynchronous Perl: Coro asynchronous
Perl: Coro asynchronous
 

Destacado (20)

Edisi 12 Medan
Edisi 12 MedanEdisi 12 Medan
Edisi 12 Medan
 
15jan Aceh
15jan Aceh15jan Aceh
15jan Aceh
 
BI Portfolio
BI PortfolioBI Portfolio
BI Portfolio
 
Fvcp Presentation Openoffice
Fvcp Presentation OpenofficeFvcp Presentation Openoffice
Fvcp Presentation Openoffice
 
Edisi1oktaceh
Edisi1oktacehEdisi1oktaceh
Edisi1oktaceh
 
Credit Its A Brand New Day
Credit Its A Brand New DayCredit Its A Brand New Day
Credit Its A Brand New Day
 
Ocean lifeguard expo 2010
Ocean lifeguard expo 2010Ocean lifeguard expo 2010
Ocean lifeguard expo 2010
 
Edisi Nasional 27 Maret
Edisi Nasional 27 MaretEdisi Nasional 27 Maret
Edisi Nasional 27 Maret
 
Edisi 28 Medan
Edisi 28 MedanEdisi 28 Medan
Edisi 28 Medan
 
Severe Weather2010 Mar12
Severe Weather2010 Mar12Severe Weather2010 Mar12
Severe Weather2010 Mar12
 
Edisi 7 Feb 2010
Edisi 7 Feb 2010Edisi 7 Feb 2010
Edisi 7 Feb 2010
 
12jan Aceh
12jan Aceh12jan Aceh
12jan Aceh
 
TIM Day in NY
TIM Day in NYTIM Day in NY
TIM Day in NY
 
Stres
StresStres
Stres
 
Edisi 2 Maret Medan
Edisi 2 Maret MedanEdisi 2 Maret Medan
Edisi 2 Maret Medan
 
2 Des Aceh
2 Des Aceh2 Des Aceh
2 Des Aceh
 
Skapa en sökmotorvänlig webbplats!
Skapa en sökmotorvänlig webbplats!Skapa en sökmotorvänlig webbplats!
Skapa en sökmotorvänlig webbplats!
 
Edisi 1 Maret Medan
Edisi 1 Maret MedanEdisi 1 Maret Medan
Edisi 1 Maret Medan
 
Top Flex 7 Unit One- phrasal verbs
Top Flex 7 Unit One- phrasal verbsTop Flex 7 Unit One- phrasal verbs
Top Flex 7 Unit One- phrasal verbs
 
Webinarium affiliate
Webinarium affiliateWebinarium affiliate
Webinarium affiliate
 

Similar a Fun with Ruby and Cocoa

Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshare
tomcopeland
 
Advanced JavaScript Development
Advanced JavaScript DevelopmentAdvanced JavaScript Development
Advanced JavaScript Development
Jussi Pohjolainen
 
Node.js basics
Node.js basicsNode.js basics
Node.js basics
Ben Lin
 
A tour on ruby and friends
A tour on ruby and friendsA tour on ruby and friends
A tour on ruby and friends
旻琦 潘
 

Similar a Fun with Ruby and Cocoa (20)

From Zero To Production (NixOS, Erlang) @ Erlang Factory SF 2016
From Zero To Production (NixOS, Erlang) @ Erlang Factory SF 2016From Zero To Production (NixOS, Erlang) @ Erlang Factory SF 2016
From Zero To Production (NixOS, Erlang) @ Erlang Factory SF 2016
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshare
 
Complex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxComplex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBox
 
Advanced JavaScript Development
Advanced JavaScript DevelopmentAdvanced JavaScript Development
Advanced JavaScript Development
 
infra-as-code
infra-as-codeinfra-as-code
infra-as-code
 
Bulding a reactive game engine with Spring 5 & Couchbase
Bulding a reactive game engine with Spring 5 & CouchbaseBulding a reactive game engine with Spring 5 & Couchbase
Bulding a reactive game engine with Spring 5 & Couchbase
 
DevOps in PHP environment
DevOps in PHP environment DevOps in PHP environment
DevOps in PHP environment
 
Node.js basics
Node.js basicsNode.js basics
Node.js basics
 
Vagrant for real
Vagrant for realVagrant for real
Vagrant for real
 
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
 
Node Boot Camp
Node Boot CampNode Boot Camp
Node Boot Camp
 
A tour on ruby and friends
A tour on ruby and friendsA tour on ruby and friends
A tour on ruby and friends
 
Getting Started with iBeacons (Designers of Things 2014)
Getting Started with iBeacons (Designers of Things 2014)Getting Started with iBeacons (Designers of Things 2014)
Getting Started with iBeacons (Designers of Things 2014)
 
Splunk n-box-splunk conf-2017
Splunk n-box-splunk conf-2017Splunk n-box-splunk conf-2017
Splunk n-box-splunk conf-2017
 
MyShell - English
MyShell - EnglishMyShell - English
MyShell - English
 
Continuous Delivery: The Next Frontier
Continuous Delivery: The Next FrontierContinuous Delivery: The Next Frontier
Continuous Delivery: The Next Frontier
 
MINCS - containers in the shell script (Eng. ver.)
MINCS - containers in the shell script (Eng. ver.)MINCS - containers in the shell script (Eng. ver.)
MINCS - containers in the shell script (Eng. ver.)
 
Présentation "Docker + Kubernetes" @ Pastis.tech #2
Présentation "Docker + Kubernetes" @ Pastis.tech #2Présentation "Docker + Kubernetes" @ Pastis.tech #2
Présentation "Docker + Kubernetes" @ Pastis.tech #2
 
Node.js - async for the rest of us.
Node.js - async for the rest of us.Node.js - async for the rest of us.
Node.js - async for the rest of us.
 
No Callbacks, No Threads - RailsConf 2010
No Callbacks, No Threads - RailsConf 2010No Callbacks, No Threads - RailsConf 2010
No Callbacks, No Threads - RailsConf 2010
 

Más de Patrick Huesler

Más de Patrick Huesler (9)

Technical Challenges of Developing a Facebook Game
Technical Challenges of Developing a Facebook GameTechnical Challenges of Developing a Facebook Game
Technical Challenges of Developing a Facebook Game
 
Culerity and Headless Full Stack Integration Testing
Culerity and Headless Full Stack Integration TestingCulerity and Headless Full Stack Integration Testing
Culerity and Headless Full Stack Integration Testing
 
Client Side Optimization
Client Side OptimizationClient Side Optimization
Client Side Optimization
 
Building and deploying Cocoa applications with ChocTop
Building and deploying Cocoa applications with ChocTopBuilding and deploying Cocoa applications with ChocTop
Building and deploying Cocoa applications with ChocTop
 
Choctop Lightning talk EuRuKo 2010
Choctop Lightning talk EuRuKo 2010Choctop Lightning talk EuRuKo 2010
Choctop Lightning talk EuRuKo 2010
 
Small Cocoa Apps with MacRuby
Small Cocoa Apps with MacRubySmall Cocoa Apps with MacRuby
Small Cocoa Apps with MacRuby
 
Erlang, an overview
Erlang, an overviewErlang, an overview
Erlang, an overview
 
Migrating legacy data
Migrating legacy dataMigrating legacy data
Migrating legacy data
 
Active Record No No's
Active Record No No'sActive Record No No's
Active Record No No's
 

Último

Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Último (20)

Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 

Fun with Ruby and Cocoa

  • 1. Ruby and Cocoa Facilitate development on OSX
  • 10. Ruby
  • 13.
  • 17. Cocoa
  • 18. Cocoa • Core Foundation
  • 19. Cocoa • Core Foundation • Appkit
  • 20. Cocoa • Core Foundation • Appkit • Core * (Audio/Video/Image/Data etc.)
  • 21. Cocoa • Core Foundation • Appkit • Core * (Audio/Video/Image/Data etc.) • Scripting bridge
  • 22. Cocoa • Core Foundation • Appkit • Core * (Audio/Video/Image/Data etc.) • Scripting bridge • others
  • 24. XCode
  • 26. NSMutableArray *anArray = [ [NSMutableArray alloc] init ]; [anArray addObject:@"Element 1"]; [anArray addObject:@"Element 2"]; [anArray addObject:@"Element 3"]; //Use a for each loop to iterate through the array for (NSString *s in anArray) { NSLog(s); } //Release the array [anArray release]
  • 27.
  • 29.
  • 31.
  • 32. HotCocoa picture shamelessly cropped from http://www.slideshare.net/mattetti/macruby-hotcocoa-presentation-by-rich-kilmer
  • 33. Scripting Bridge http://www.flickr.com/photos/bensonkua/2851908095/sizes/l/
  • 35. Good to know • Available commands for each application are in a .sdef file
  • 36. Good to know • Available commands for each application are in a .sdef file • Terminal.app/Contents/Resources/ Terminal.sdef
  • 37. Good to know • Available commands for each application are in a .sdef file • Terminal.app/Contents/Resources/ Terminal.sdef • gem rb-appscript (native extension so not for MacRuby)
  • 38. 1 <command name="do script" code="coredosc" 2 description="Runs a UNIX shell script or command."> 3 <cocoa class="TTDoScriptCommand"/> 4 <direct-parameter type="text" 5 description="The command to execute." optional="yes"/> 6 <parameter name="with command" 7 description="Data to be passed to the Terminal..." 8 code="cmnd" optional="yes" hidden="yes"> 9 <cocoa key="Command" /> 10 <type type="text" /> 11 <type type="any" /> <!-- support null case --> 12 </parameter> 13 <parameter name="in" 14 description="The tab in which to execute the command" 15 code="kfil" optional="yes"> 16 <cocoa key="Target" /> 17 <type type="tab" /> 18 <type type="window" /> 19 <type type="any" /> <!-- support null case --> 20 </parameter> 21 <result type="tab" 22 description="The tab the command was executed in." /> 23 </command> 24
  • 39.
  • 41. 1 #!/usr/bin/env ruby 2 require 'rubygems' 3 require 'appscript' 4 include Appscript 5 6 terminal = app('Terminal') 7 current_window = terminal.windows.first 8 current_tab = current_window.tabs.last 9 process = app("System Events").application_processes[ 10 "Terminal.app" 11 ] 12 13 process.keystroke('t', :using => :command_down) 14 terminal.do_script('top', :in => current_tab)
  • 42. 1 #!/usr/bin/env ruby 2 require 'rubygems' 3 require 'appscript' 4 include Appscript 5 6 terminal = app('Terminal') 7 current_window = terminal.windows.first 8 current_tab = current_window.tabs.last 9 process = app("System Events").application_processes[ 10 "Terminal.app" 11 ] 12 13 process.keystroke('t', :using => :command_down) 14 terminal.do_script('top', :in => current_tab)
  • 43. 1 #!/usr/bin/env ruby 2 require 'rubygems' 3 require 'appscript' 4 include Appscript 5 6 terminal = app('Terminal') 7 current_window = terminal.windows.first 8 current_tab = current_window.tabs.last 9 process = app("System Events").application_processes[ 10 "Terminal.app" 11 ] 12 13 process.keystroke('t', :using => :command_down) 14 terminal.do_script('top', :in => current_tab)
  • 44. 7 current_window = terminal.windows.first 8 current_tab = current_window.tabs.last 9 process = app("System Events").application_processes[ 10 "Terminal.app" 11 ] 12 13 process.keystroke('t', :using => :command_down) 14 terminal.do_script('top', :in => current_tab)
  • 47. Problems with MacRuby • Some methods don’t seem to be available
  • 49. 1 #!/usr/bin/env macruby 2 3 framework 'ScriptingBridge' 4 5 itunes = SBApplication.applicationWithBundleIdentifier( 6 "com.apple.iTunes" 7 ) 8 library = itunes.sources.objectWithName ("Library") 9 10 library.userPlaylists.each do |playlist| 11 puts playlist.name 12 end
  • 50. 2 3 framework 'ScriptingBridge' 4 5 itunes = SBApplication.applicationWithBundleIdentifier( 6 "com.apple.iTunes" 7 ) 8 library = itunes.sources.objectWithName ("Library") 9 10 library.userPlaylists.each do |playlist| 11 puts playlist.name 12 end
  • 51. 2 3 framework 'ScriptingBridge' 4 5 itunes = SBApplication.applicationWithBundleIdentifier( 6 "com.apple.iTunes" 7 ) 8 library = itunes.sources.objectWithName ("Library") 9 10 library.userPlaylists.each do |playlist| 11 puts playlist.name 12 end
  • 53. 1 #!/usr/bin/env macruby 2 framework 'CoreLocation' 3 4 loc = CLLocationManager.alloc.init 5 loc.delegate = self 6 loc.startUpdatingLocation 7 8 # keep the script running 9 NSRunLoop.currentRunLoop.runUntilDate( 10 NSDate.distantFuture 11 )
  • 54. 1 #!/usr/bin/env macruby 2 framework 'CoreLocation' 3 4 loc = CLLocationManager.alloc.init 5 loc.delegate = self 6 loc.startUpdatingLocation 7 8 # keep the script running 9 NSRunLoop.currentRunLoop.runUntilDate( 10 NSDate.distantFuture 11 )
  • 55. 1 def locationManager( 2 manager, 3 didUpdateToLocation: new_location, 4 fromLocation: old_location 5 ) 6 7 puts "loc: #{new_location.description}" 8 end
  • 56. 2 framework 'CoreLocation' 3 4 loc = CLLocationManager.alloc.init 5 loc.delegate = self 6 loc.startUpdatingLocation 7 8 # keep the script running 9 NSRunLoop.currentRunLoop.runUntilDate( 10 NSDate.distantFuture 11 )
  • 57. 1 #!/usr/bin/env macruby 2 framework 'CoreLocation' 3 4 def locationManager(manager, 5 didUpdateToLocation: new_location, 6 fromLocation: old_location 7 ) 8 puts "location: #{new_location.description}" 9 end 10 11 loc = CLLocationManager.alloc.init 12 loc.delegate = self 13 loc.startUpdatingLocation 14 15 # keep the script running 16 NSRunLoop.currentRunLoop.runUntilDate( 17 NSDate.distantFuture 18 )
  • 58. Grand Central Dispatch
  • 61. Grand Central Dispatch • MacRuby only • Synchronous
  • 62. Grand Central Dispatch • MacRuby only • Synchronous • Asynchronous
  • 63. Grand Central Dispatch • MacRuby only • Synchronous • Asynchronous • Parallel
  • 64. Grand Central Dispatch • MacRuby only • Synchronous • Asynchronous • Parallel • Synchronization
  • 66. 1 #!/usr/bin/env macruby 2 3 queue = Dispatch::Queue.new( 4 'ch.huesler-informatik.scotrubyconf.gcd' 5 ) 6 7 queue.async do 8 puts 'Starting asyn. NONE BLOCKING!' 9 sleep 2.00 10 puts "Finished asyn" 11 end 12 puts "code not being blocked" 13 14 NSRunLoop.currentRunLoop.runUntilDate( 15 NSDate.distantFuture 16 ) 17
  • 67. 1 #!/usr/bin/env macruby 2 3 queue = Dispatch::Queue.new( 4 'ch.huesler-informatik.scotrubyconf.gcd' 5 ) 6 7 queue.async do 8 puts 'Starting asyn. NONE BLOCKING!' 9 sleep 2.00 10 puts "Finished asyn" 11 end 12 puts "code not being blocked" 13 14 NSRunLoop.currentRunLoop.runUntilDate( 15 NSDate.distantFuture 16 ) 17
  • 68. 7 queue.async do 8 puts 'Starting asyn. NONE BLOCKING!' 9 sleep 2.00 10 puts "Finished asyn" 11 end 12 puts "code not being blocked" 13 14 NSRunLoop.currentRunLoop.runUntilDate( 15 NSDate.distantFuture 16 ) 17
  • 70. 1 #!/usr/bin/env macruby 2 3 queue = Dispatch::Queue.new( 4 'ch.huesler-informatik.scotrubyconf.gcd' 5 ) 6 7 queue.sync do 8 puts 'Starting sync. BLOCKING!' 9 sleep 3.0 10 puts 'Finished sync' 11 end 12 puts "code being blocked" 13 14 NSRunLoop.currentRunLoop.runUntilDate( 15 NSDate.distantFuture 16 ) 17
  • 72. 1 #!/usr/bin/env macruby 2 3 worker_queue = Dispatch::Queue.new( 4 'ch.huesler-informatik.scotrubyconf.gcd' 5 ) 6 group = Dispatch::Group.new 7 8 0.upto(10) do |i| 9 puts "Dispatch #{i} to GCD" 10 worker_queue.async(group) do 11 puts "working on #{i}" 12 end 13 end 14 puts "waiting for gcd" 15 group.wait 16 puts "done" 17
  • 73. 1 #!/usr/bin/env macruby 2 3 worker_queue = Dispatch::Queue.new( 4 'ch.huesler-informatik.scotrubyconf.gcd' 5 ) 6 group = Dispatch::Group.new 7 8 0.upto(10) do |i| 9 puts "Dispatch #{i} to GCD" 10 worker_queue.async(group) do 11 puts "working on #{i}" 12 end 13 end 14 puts "waiting for gcd" 15 group.wait 16 puts "done" 17
  • 74. 7 8 0.upto(10) do |i| 9 puts "Dispatch #{i} to GCD" 10 worker_queue.async(group) do 11 puts "working on #{i}" 12 end 13 end 14 puts "waiting for gcd" 15 group.wait 16 puts "done" 17
  • 76. 1 #!/usr/bin/env macruby 2 3 group = Dispatch::Group.new 4 result = [] 5 1.upto(10).each do |i| 6 Dispatch::Queue.concurrent.async(group) do 7 sleep 2 8 result << i 9 end 10 end 11 group.wait 12 puts result.inspect
  • 78. 1 #!/usr/bin/env ruby 2 require "osx/cocoa" 3 include OSX 4 5 file_name = 'Info.plist' 6 plist = NSDictionary.dictionaryWithContentsOfFile( 7 file_name 8 ) 9 10 plist['CFBundleVersion'] = '2.0.1' 11 12 plist.writeToFile_atomically( 13 file_name, 14 true 15 )
  • 79. 1 #!/usr/bin/env ruby 2 require "osx/cocoa" 3 include OSX 4 5 file_name = 'Info.plist' 6 plist = NSDictionary.dictionaryWithContentsOfFile( 7 file_name 8 ) 9 10 plist['CFBundleVersion'] = '2.0.1' 11 12 plist.writeToFile_atomically( 13 file_name, 14 true 15 )
  • 80. 3 include OSX 4 5 file_name = 'Info.plist' 6 plist = NSDictionary.dictionaryWithContentsOfFile( 7 file_name 8 ) 9 10 plist['CFBundleVersion'] = '2.0.1' 11 12 plist.writeToFile_atomically( 13 file_name, 14 true 15 )
  • 83. Details • MacRuby has issues with void pointer (patch pending)
  • 84. Details • MacRuby has issues with void pointer (patch pending) • Use objective c wrapper instead (dynlib or bundle)
  • 85. Details • MacRuby has issues with void pointer (patch pending) • Use objective c wrapper instead (dynlib or bundle) • Generate metadata to make it work
  • 86. Details • MacRuby has issues with void pointer (patch pending) • Use objective c wrapper instead (dynlib or bundle) • Generate metadata to make it work
  • 87. 1 export FILE_PATH = ~/Library/BridgeSupport 2 export FRAMEWORK_PATH = ~/Library/BridgeSupport/ Security.bridgesupport 3 mkdir $FILE_PATH 4 gen_bridge_metadata -f Security -o $FRAMEWORK_PATH
  • 88. 1 require 'osx/cocoa' 2 include OSX 3 require_framework 'Security' 4 5 # Set up some relevant variables 6 7 service = "ch.huesler-informatik.scotrubyconf.keychain" 8 account = "Highlander" 9 original_password = "Rrrueby" 10 11 # Add password 12 SecKeychainAddGenericPassword( 13 nil, 14 service.length, 15 service, 16 account.length, 17 account, 18 original_password.length, 19 original_password, 20 nil 21 )
  • 89. 1 require 'osx/cocoa' 2 include OSX 3 require_framework 'Security' 4 5 # Set up some relevant variables 6 7 service = "ch.huesler-informatik.scotrubyconf.keychain" 8 account = "Highlander" 9 original_password = "Rrrueby" 10 11 # Add password 12 SecKeychainAddGenericPassword( 13 nil, 14 service.length, 15 service, 16 account.length, 17 account, 18 original_password.length, 19 original_password, 20 nil 21 )
  • 90. 1 # Add password 2 SecKeychainAddGenericPassword( 3 nil, 4 service.length, 5 service, 6 account.length, 7 account, 8 original_password.length, 9 original_password, 10 nil 11 )
  • 91. 1 # Query the keychain 2 status, *password = SecKeychainFindGenericPassword( 3 nil, 4 service.length, 5 service, 6 account.length, 7 account 8 )
  • 92. 1 # Password-related data. Shifting pointers 2 length = password.shift 3 data = password.shift 4 plain_password = data.bytestr(length) 5 6 puts "Password: #{plain_password}"