[macruby-changes] [4515] MacRubyWebsite/trunk/content

source_changes at macosforge.org source_changes at macosforge.org
Tue Sep 14 03:12:18 PDT 2010


Revision: 4515
          http://trac.macosforge.org/projects/ruby/changeset/4515
Author:   joshua.ballanco at apple.com
Date:     2010-09-14 03:12:14 -0700 (Tue, 14 Sep 2010)
Log Message:
-----------
First draft of ControlTower announcement

Modified Paths:
--------------
    MacRubyWebsite/trunk/content/css/master.css
    MacRubyWebsite/trunk/content/documentation/gcd.txt
    MacRubyWebsite/trunk/content/documentation/rubycocoa-to-macruby.txt

Added Paths:
-----------
    MacRubyWebsite/trunk/content/blog/2010/09/
    MacRubyWebsite/trunk/content/blog/2010/09/16/
    MacRubyWebsite/trunk/content/blog/2010/09/16/announcing-control-tower.txt
    MacRubyWebsite/trunk/content/blog/2010/09/index.txt

Added: MacRubyWebsite/trunk/content/blog/2010/09/16/announcing-control-tower.txt
===================================================================
--- MacRubyWebsite/trunk/content/blog/2010/09/16/announcing-control-tower.txt	                        (rev 0)
+++ MacRubyWebsite/trunk/content/blog/2010/09/16/announcing-control-tower.txt	2010-09-14 10:12:14 UTC (rev 4515)
@@ -0,0 +1,74 @@
+---
+title:      ControlTower
+created_at: 2010-09-16 11:57:25.075413 -04:00
+blog_post:  true
+layout:     blog_entry
+author:     Joshua Ballanco
+filter:
+  - erb
+  - textile
+---
+<% @page[:excerpt] = capture_erb do %>
+We are pleased to announce the first version of ControlTower, a Rack-based web application server for Ruby. ControlTower can already run basic rack and Sinatra apps, but there are still a lot of features to add.
+<% end %>
+
+h3. "It's called ControlTower!":http://www.youtube.com/watch?v=QbdXt2K27NU
+
+Way back in the announcement for MacRuby 0.5, we cryptically mentioned that we had gotten a web server to run a basic Sinatra app. While that statement was true, the server we had wasn't even really alpha worthy. At that point, it was more about proof of concept. If you have been watching the subversion repository you might have noticed that a new top-level project appeared about 4 months ago. If you're subscribed to the mailing list, you probably have even seen a bit of discussion take place about this project, and yet we still weren't quite ready to announce it to the world. Well, that changes today!
+
+Today we are officially announcing version 0.1 of ControlTower, the Rack-based web app server for MacRuby.
+
+If you're a casual follower of MacRuby, here is what you need to know in a nut-shell:
+
+<div class="control-tower">
+* ControlTower is a Rack-based web application server, written from the ground for MacRuby
+* It takes advantage of MacRuby's ability to mix-n-match Cocoa APIs with Ruby, so it will (for the forseable future) _only_ run on MacRuby
+* It can be used on its own or with a reverse proxy to serve any Rack-based web app whose libraries are supported by MacRuby (i.e. Sinatra, but not Rails...yet)
+* We are also interested in other non-traditional ways an embeddable Ruby web app server might be useful for native app development
+* It's small, it's light weight, and it's reasonably fast
+<div>
+<br />
+
+h3. How do I use it?
+
+To get ControlTower, you can checkout the source using subversion at @http://svn.macosforge.org/repository/ruby/ControlTower/tags/0.1@. Once you have the source you can use rake to build the gem (requires developer tools) and macgem to install like so:
+
+<pre class="commands">
+$ rake gem
+$ sudo macgem install pkg/control_tower-0.1-universal-darwin-10.gem
+</pre>
+
+There are two basic ways to interact with a Rack-based web server: create a rack-up file, or use a Rack::Handler in your code. Currently, both of these mechanisms work with ControlTower. Using a rack-up file is probably the simplest and most straight forward way to get up and running, and we've included a number of sample rack-up files in the "sample" directory of the repository. Once you have built and installed the ControlTower gem, you can use the @control_tower@ command to run any rack-up config:
+
+<pre class="commands">
+$ control_tower -R sample/simple_hello.ru
+You are cleared for take-off!
+Listening on 0.0.0.0:3000
+</pre>
+
+Alternatively, if you would like to start up the ControlTower server from within your code, you can use the @Rack::Handler::ControlTower@ class included with the ControlTower gem. This class has a single @run@ method that takes a rack "app" object and an options hash as its arguments. The options hash can be used to set the same server parameters as the command line tool. So, for example you can do:
+
+<%- coderay :lang => 'ruby' do -%>
+app = MyApp.new
+Rack::Handle::ControlTower.run(app, {:port => 80,
+                                     :host => 'myserver.com',
+                                     :concurrent => true })
+<%- end -%>
+
+Though, keep in mind that this method will block untill the server stops running, so if you want to do something else while the server is running you should put this code in a thread.
+<br />
+
+h3. What's in a Web Server?
+
+In general, all Ruby web app servers consist of the same three components: a socket manager, a header parser, and a request handler. Incoming requests initially encounter the socket manager which begins receiving data from the incoming connection. This data is then fed to the header parser until all of the headers have been received. These headers, along with any request body data (e.g. a form being POSTed), are then passed on to the request handler. The request handler makes any necessary changes on the server, gathers any data needed for a reply, and then sends that reply back to the socket manager which will send the reply back to the client.
+
+Ever since Mongrel, just about every Ruby web app server has used Zed Shaw's Ragel-based HTTP parser to parse headers on incoming requests, and ControlTower does too. Since the appearance of Rack, servers can count on an "app" object provided by a web app framework to handle the requests, in accordance with the Rack spec, and being a Rack-based server ControlTower relies on this as well. That leaves the socket manager as the only one of the three components that will differ considerably between servers. In the case of Thin the socket manager is an EventMachine event loop. In the case of Unicorn sockets are managed using a prefork mechanism. In ControlTower, we do our socket management with Grand Central Dispatch.
+
+The way this works is that each new incoming request is asynchronously dispatched to a GCD queue to be parsed and handled. In the default case, this queue is a serial queue, so requests are handled first-in first-out. By placing incoming requests onto a queue immediately, the server is quickly able to accept the next incoming request. If the @-c@ switch is used with the control_tower command or the @:concurrent@ key is set to true in the handler's options hash, ControlTower will use a concurrent GCD queue in place of the serial one. This means that ControlTower can handle multiple requests concurrently inside a single process; up to 75 at once on an 8-core MacPro (compared to 20 simultaneous requests per Thin process in threaded mode). If you want to give concurrent mode a try, just make sure that your web app and database layer are truly thread-safe, and not just green-thread-safe.
+<br />
+
+h3. How can I help?
+
+Glad you asked! ControlTower is still a relatively young project, so there is still lots to do. Right now, it is a small, robust server capable of handling moderate loads, but it doesn't have as many features as other Rack-based servers like Thin or Unicorn. Most notably, we do not yet support keep-alive. Other wish-list items include the addition of Rack adapters for the various common Ruby web app frameworks, support for unix domain sockets, and the ability to do Web Sockets.
+
+Of course, you don't have to be heavy into server development to lend a hand. We could use a lot of help just with testing and documentation (both of which are lacking currently). Perhaps the simplest and most important thing you can do to help is to try it out and send in your bug reports and feature requests. We started building ControlTower for our own purposes, but now we're ready to share it with the community and see where you take it.

Added: MacRubyWebsite/trunk/content/blog/2010/09/index.txt
===================================================================
--- MacRubyWebsite/trunk/content/blog/2010/09/index.txt	                        (rev 0)
+++ MacRubyWebsite/trunk/content/blog/2010/09/index.txt	2010-09-14 10:12:14 UTC (rev 4515)
@@ -0,0 +1,22 @@
+---
+title:      08
+created_at: 2010-08-09 00:57:24.985737 -04:00
+filter:     erb
+dirty:      true
+---
+<h2><%= h(@page.title) %></h2>
+
+<%
+  articles = @pages.find(:all, :in_directory => @page.dir, :recursive => true,
+      :sort_by => "created_at", :reverse => true, :blog_post => true)
+  articles.delete(@page)
+  paginate(articles, 10) do |page|
+-%>
+<div class="article">
+  <h1><%= link_to_page(page) %><span class="date">(<%= page.created_at.strftime('%Y-%m-%d') %>)</span></h1>
+
+  <div class="body">
+    <%= render(page) %>
+  </div>
+</div>
+<% end -%>

Modified: MacRubyWebsite/trunk/content/css/master.css
===================================================================
--- MacRubyWebsite/trunk/content/css/master.css	2010-09-14 04:40:54 UTC (rev 4514)
+++ MacRubyWebsite/trunk/content/css/master.css	2010-09-14 10:12:14 UTC (rev 4515)
@@ -5,6 +5,16 @@
   color: #333;
 }
 
+em {
+	font-style: italic;
+}
+
+li {
+	list-style-position: outside;
+	list-style-type: disc;
+	margin-left: 32px;
+}
+
 #logo {
   width=300px;
 }

Modified: MacRubyWebsite/trunk/content/documentation/gcd.txt
===================================================================
--- MacRubyWebsite/trunk/content/documentation/gcd.txt	2010-09-14 04:40:54 UTC (rev 4514)
+++ MacRubyWebsite/trunk/content/documentation/gcd.txt	2010-09-14 10:12:14 UTC (rev 4515)
@@ -26,7 +26,7 @@
 Queues, represented in MacRuby by the @Dispatch::Queue@ class, are data structures that execute tasks. Under the hood, GCD maintains a pool of POSIX threads to which queues dispatch their tasks; GCD will grow and shrink this pool dynamically and distribute its threads evenly among available processors.  
 Queues can execute their tasks either concurrently or sequentially. All queues begin executing tasks in the order in which they were received, but concurrent queues can run many tasks at once, whereas serial queues wait for one to complete before starting the next. GCD provides three singleton concurrent queues and allows the creation any number of serial queues. Performing work on a queue is extremely easy:
 
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
 # Create a new serial queue.
 queue = Dispatch::Queue.new('org.macruby.examples.gcd')
 # Synchronously dispatch some work to it.
@@ -41,7 +41,7 @@
   sleep 1.0
   puts 'Done!'
 end
-</pre>
+<%- end -%>
 
 If you paste this code into a running @macirb@ prompt, you’ll see that the queue blocks until the task specified in the @#sync@ block is finished, while task we specified in the block we passed to the @#async@ method is executed asynchronously in the background.
 
@@ -51,7 +51,7 @@
 
 Ensuring that methods and data are accessed by one and only one thread at a time is a common problem in software development today. However, unlike languages such as Java and Objective-C, Ruby has no built-in language support for synchronization, relying instead on the Mutex and Monitor classes. However, GCD introduces another elegant idiom for synchronization that is higher-level than Mutex and significantly simpler than Monitor:
 
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
 class MissileLauncher
   def initialize
     @queue = Dispatch::Queue.new('org.macruby.synchronizer')
@@ -65,7 +65,7 @@
     end
   end
 end
-</pre>
+<%- end -%>
 
 h3. Synchronization with Groups
 
@@ -75,7 +75,7 @@
 
 Languages like "Io":http://www.iolanguage.com/ and "Oz":http://www.mozart-oz.org/ provide the notion of "futures":http://en.wikipedia.org/wiki/Futures_and_promises: proxy objects that perform expensive computations in the background. By using GCD queues to execute the tasks and groups to synchronize the tasks’ execution, we have a simple, concise and reliable implementation of futures in MacRuby:
 
-<pre class="commands">
+<%- coderay :laungage => 'ruby' do -%>
 include Dispatch
 class Future
   def initialize(&block)
@@ -93,16 +93,17 @@
     @value
   end
 end
-</pre>
+<%- end -%>
+
 Now it’s easy to schedule long-running tasks in the background:
 
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
 some_result = Future.new do
   p 'Engaging delayed computation!'
   sleep 2.5
   :done # Your result would go here.
 end
-</pre>
+<%- end -%>
 
 Accessing the value is as easy as calling @some_result.value at .
 
@@ -110,7 +111,7 @@
 
 Now let’s see an example of how easy it is to parallelize your code with the GCD’s groups and concurrent queues:
 
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
 class Array
   def parallel_map(&block)
     result = []
@@ -131,7 +132,7 @@
     result
   end
 end
-</pre>
+<%- end -%>
 
 This example uses the queue accessed through @Dispatch::Queue.concurrent@ to speed up @Array#map@ by spreading out the total work across the system’s available processors. From a two-core Macbook Air to a 16-core Mac Pro, GCD executes the tasks dispatched on the concurrent queue across all available processors. With fewer than a dozen lines of code, we’ve parallelized @#map@ and avoided race conditions by using groups to synchronize.
 

Modified: MacRubyWebsite/trunk/content/documentation/rubycocoa-to-macruby.txt
===================================================================
--- MacRubyWebsite/trunk/content/documentation/rubycocoa-to-macruby.txt	2010-09-14 04:40:54 UTC (rev 4514)
+++ MacRubyWebsite/trunk/content/documentation/rubycocoa-to-macruby.txt	2010-09-14 10:12:14 UTC (rev 4515)
@@ -20,19 +20,19 @@
 
 To import a framework in RubyCocoa, you use a combination of Ruby's @require@ method and RubyCocoa's @require_framework@ addition:
 
-<pre class="commands">
+<%- coderay :languag => 'ruby' do -%>
 # RubyCocoa code
 require 'osx/cocoa'
 OSX.require_framework('CoreData')
-</pre>
+<%- end -%>
 
 MacRuby unifies these methods with the @framework@ method added to the @Kernel@ module:
 
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
 # MacRuby code
 framework 'Cocoa'
 framework 'CoreData'
-</pre>
+<%- end -%>
 
 h3. Namespaces
 
@@ -42,19 +42,19 @@
 
 Because RubyCocoa is not implemented on top of Objective-C, it requires objects passed to Objective-C APIs to inherit from @NSObject@:
 
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
 # RubyCocoa code
 class MyClass < NSObject
 end
-</pre>
+<%- end -%>
 
 In MacRuby, the Objective-C @NSObject@ and Ruby @Object@ classes are identical; therefore, because Ruby classes implicitly inherit from @Object@, all objects in MacRuby are valid @NSObjects at . Explicit inheritance is therefore no longer required:
 
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
 # MacRuby code
 class MyClass
 end
-</pre>
+<%- end -%>
 
 h3. Class Compatibility
 
@@ -81,14 +81,14 @@
 
 Because Cocoa code often requires working with C struct types, MacRuby allows you to pass in an @Array@ containing the required data where a C struct would normally be expected. Some examples follow: 
 
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
 # MacRuby code
 window.frame = NSMakeRect(0, 0, 100, 200) 	# Using the NSMakeRect function
 window.frame = NSRect.new(NSPoint.new(0, 0),	# Using the MacRuby NSRect class
                           NSSize.new(100, 200))
 window.frame = [0, 0, 100, 200]			# Using a array in flat style 
 window.frame = [[0, 0], [100, 200]]		# Using an array [point, size] style
-</pre>
+<%- end -%>
 
 Please note that MacRuby's @Range@, @Set@, and @Enumerator@ classes are *not* bridged to their Cocoa or CoreFoundation equivalents.
 
@@ -96,28 +96,28 @@
 
 Objective-C's interleaved-keyword syntax is not compatible with traditional Ruby syntax. To be able to call Cocoa API's from RubyCocoa, you use the "underscore hack", which translates Ruby-style function calls into ObjC calls by joining the selector's components together with underscores:
 
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
 # RubyCocoa code
 NSFileManager.defaultManager.createFileAtPath_contents_attributes(p, c, a)
-</pre>
+<%- end -%>
 
 In order to make the use of Objective-C methods from MacRuby as natural as possible, the MacRuby team extended standard Ruby syntax to support Objective-C style interleaved arguments:
 
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
 # MacRuby code
 NSFileManager.defaultManager.createFileAtPath(p, contents:c, attributes:a)
-</pre>
+<%- end -%>
 
 This is the best way to call Objective-C methods; code written using the underscore hack or RubyCocoa's @objc_send@ function will fail to run under MacRuby.
 MacRuby allows you to use this syntax in your own method declarations, too:
 
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
 # MacRuby code
 def saveWorld(planet, fromVillain: badguy, withHero:superhero)
   superhero.fight(badguy)
   planet.thank(superhero)
 end
-</pre>
+<%- end -%>
 
 However, it's important to note that this syntax is unique to MacRuby; code written in that uses this syntax will fail to run on any other implementation of Ruby.
 
@@ -125,50 +125,50 @@
 
 MacRuby's integration with Interface Builder is significantly cleaner than RubyCocoa's. Previously, declaring an instance variable that also functioned as an Interface Builder outlet required two declarations, one to declare Ruby-style accessors and another to declare a key-value compliant accessor:
 
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
 # RubyCocoa code
 class MyView < NSView
   attr_accessor :pdfView
   ib_outlet :pdfView
 end
-</pre>
+<%- end -%>
 
 MacRuby extends the semantics of @attr_accessor@ and @attr_writer@ to provide a key-value compliant setter method that Interface Builder will recognize. As such, all references to the @ib_outlet@ method can be removed:
 
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
 # MacRuby code
 class MyView < NSView
   attr_accessor :pdfView
 end
-</pre>
+<%- end -%>
 
 Another significant improvement comes in the form of transparent support for Interface Builder actions. RubyCocoa required that IB actions be declared with the @ib_action@ helper method:
 
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
 # RubyCocoa code
 class MyController < NSObject
   ib_action(:firstPage) do |sender|
     currentPDFView.setPageNumber(1)
   end
 end
-</pre>
+<%- end -%>
 
 Because of MacRuby's tight integration with the Objective-C runtime, there is no special syntax required to declare an IB action: any Ruby method can serve as an IB action, though it must have a @sender@ parameter like in Objective-C:
 
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
 # MacRuby code
 class MyController
   def firstPage(sender)
     currentPDFView.pageNumber = 1
   end
 end
-</pre>
+<%- end -%>
 
 h3. super()
 
 In RubyCocoa, the @super()@ function did not work correctly if the superclass method being called was implemented in Objective-C. A further extension to the underscore hack became necessary:
 
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
 # RubyCocoa code
 class MyClass < NSObject
   def init
@@ -177,11 +177,11 @@
     self		# Always return self from init!
   end
 end
-</pre>
+<%- end -%>
 
 MacRuby rectifies this inconsistency, allowing the @super()@ function to call both Ruby and Objective-C methods:
 
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
 # MacRuby code
 class MyClass
   def init
@@ -190,7 +190,7 @@
     self		# Always return self from init!
   end
 end
-</pre>
+<%- end -%>
 
 h3. Exception Handling
 
@@ -200,38 +200,38 @@
 
 The MacRuby team has ported the syntactic extensions present in RubyCocoa for cases when Objective-C idioms differ with Ruby idioms, such as in the case of mutator methods and boolean accessor methods:
 
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
 layer.setPosition([100, 100])	# Objective-C style
 layer.position = [100, 100]	# Ruby style; calls the same method the Objective-C one does
 layer.isHidden			# Objective-C style
 layer.hidden?			# Ruby allows the '?' character in method names
-</pre>
+<%- end -%>
 
 MacRuby provides additional syntax for the commonly-used @objectForKey:@ and @setObject:forKey:@ methods:
 
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
 obj.objectForKey('data')			# Objective-C style
 obj['data']					# Ruby style
 obj.setObject('mystery', forKey: 'data') 	# Objective-C style
 obj['data'] = 'mystery'				# Ruby style
-</pre>
+<%- end -%>
 
 h3. Property Lists
 
 RubyCocoa added extensions for easy manipulation of property lists:
 
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
 # RubyCocoa code
 array_data = ['a', 'b', 'c'].to_plist
 OSX.load_plist(array_data)
-</pre>
+<%- end -%>
 
 MacRuby ports these extensions, adding @load_plist@ to the @Kernel@ module and @to_plist@ to @Object@:
 
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
 # MacRuby code
 array_data = ['a', 'b', 'c'].to_plist
 load_plist(array_data)
-</pre>
+<%- end -%>
 
 </div>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100914/1401fa41/attachment-0001.html>


More information about the macruby-changes mailing list