<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Dr Nic &#187; DSL</title>
	<atom:link href="http://drnicwilliams.com/category/dsl/feed/" rel="self" type="application/rss+xml" />
	<link>http://drnicwilliams.com</link>
	<description>Ruby makes Rails, Javascript makes Ajax, Dr Nic makes Magic</description>
	<lastBuildDate>Tue, 03 Aug 2010 23:44:48 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Magic Multi-Connections: A &#8220;facility in Rails to talk to more than one database at a time&#8221;</title>
		<link>http://drnicwilliams.com/2007/04/12/magic-multi-connections-a-facility-in-rails-to-talk-to-more-than-one-database-at-a-time/</link>
		<comments>http://drnicwilliams.com/2007/04/12/magic-multi-connections-a-facility-in-rails-to-talk-to-more-than-one-database-at-a-time/#comments</comments>
		<pubDate>Thu, 12 Apr 2007 21:26:17 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Announcement]]></category>
		<category><![CDATA[DSL]]></category>
		<category><![CDATA[Magic Models]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Trick]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/2007/04/12/magic-multi-connections-a-facility-in-rails-to-talk-to-more-than-one-database-at-a-time/</guid>
		<description><![CDATA[At this point in time there’s no facility in Rails to talk to more than one database at a time. Alex Payne I possibly have such a facility. Perhaps it will help, and I will get some DHH-love and perhaps a free Twitter account for my troubles. Or perhaps a t-shirt. As a bonus, the [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2010/03/15/using-coffeescript-in-rails-and-even-on-heroku/' rel='bookmark' title='Permanent Link: Using CoffeeScript in Rails and even on Heroku'>Using CoffeeScript in Rails and even on Heroku</a> <small>I&#8217;m pretty excited about CoffeeScript as a clean-syntax replacement for...</small></li><li><a href='http://drnicwilliams.com/2009/11/03/first-look-at-rails-3-0-pre/' rel='bookmark' title='Permanent Link: First look at rails 3.0.pre'>First look at rails 3.0.pre</a> <small> This article is out of date in some aspects....</small></li><li><a href='http://drnicwilliams.com/2009/10/07/rails-themes-can-remember-things/' rel='bookmark' title='Permanent Link: Rails themes can remember things'>Rails themes can remember things</a> <small>I was getting annoyed at having to remember all the...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<blockquote><p>At this point in time there’s no facility in Rails to talk to more than one database at a time.</p></blockquote>
<p><cite><a href="http://www.radicalbehavior.com/5-question-interview-with-twitter-developer-alex-payne/">Alex Payne</a></cite></p>
<p>I possibly have such a <em>facility</em>. Perhaps it will help, and I will get some <a href="http://www.loudthinking.com/arc/000608.html">DHH-love</a> and perhaps a free <a href="http://www.twitter.com">Twitter</a> account for my troubles. Or perhaps a t-shirt.</p>
<p>As a bonus, the solution even includes decent Ruby-fu syntax. So, if you&#8217;re just here for the view:</p>
<pre>class PeopleController < ApplicationController
  def index
    @people = conn::Person.find(:all)
  end
end
</pre>
<p>That code just there solves all our problems. It will invoke Person.find(:all) on a random database connection to (assumably) a clone database. Awesomeness I think. I hope it helps Twitter and all the Twit-sers (or whatever you call a user of Twitter).</p>
<p>This solution comes from the <a href="http://magicmodels.rubyforge.org/magic_multi_connections">magic_multi_connections</a> gem.</p>
<h1>What is going on here?</h1>
<p>I think a tutorial is the best way to demonstrate what is happening here. So, let's create a rails app and mix in the <a href="http://magicmodels.rubyforge.org/magic_multi_connections">magic_multi_connections</a> gem.</p>
<p>First, get the gem. Second, create a rails app:</p>
<pre>$ sudo gem install magic_multi_connections
$ rails multi -d sqlite3</pre>
<p>Now edit the <code>config/database.yml</code> file to create some more databases:</p>
<pre>development:
  adapter: sqlite3
  database: db/development.sqlite3
  timeout: 5000

development_clone1:
  adapter: sqlite3
  database: db/development_clone1.sqlite3
  timeout: 5000

development_clone2:
  adapter: sqlite3
  database: db/development_clone2.sqlite3
  timeout: 5000
</pre>
<p>But please pretend these are uber-MySQL clusters or whatever.</p>
<p>Think of <strong>:development</strong> as the <strong>read-write</strong> connection, and the <strong>:development_cloneN</strong> connections are for read-only access.</p>
<p>At the bottom of your <strong>environment.rb</strong> file, add the following:</p>
<pre>
require 'magic_multi_connections'
connection_names = ActiveRecord::Base.configurations.keys.select do |name|
  name =~ /^#{ENV['RAILS_ENV']}_clone/
end
@@connection_pool = connection_names.map do |connection_name|
  Object.class_eval <<-EOS
    module #{connection_name.camelize}
      establish_connection :#{connection_name}
    end
  EOS
  connection_name.camelize.constantize
end
</pre>
<p>Let's test what this gives us in the console:</p>
<pre>$ ruby script/console
>> @@connection_pool
=> [DevelopmentClone1, DevelopmentClone2]
>> DevelopmentClone1.class
=> Module
>> DevelopmentClone1.connection_spec
=> :development_clone1
</pre>
<p>Our new modules will act as connections. One module per connection. The code above gives them names to match the connection names, but its really irrelevant what they are called, thanks to the mysterious <code>conn</code> method.</p>
<p>So, go create some models and some data. I'll use <code>Person</code> as the class here.</p>
<p>To setup the schemas in our clone databases, we'll use <code>rake db:migrate</code>. To do this:</p>
<pre>$ cp config/environments/development.rb config/environments/development_clone1.rb
$ cp config/environments/development.rb config/environments/development_clone2.rb
$ rake db:migrate RAILS_ENV=development
$ rake db:migrate RAILS_ENV=development_clone1
$ rake db:migrate RAILS_ENV=development_clone2
</pre>
<p>To differentiate the databases in our example, assume there are two <code>Person</code> records in the <code>:development</code> database, and none in the two clones. Of course, in real-life, they are clones. You'd have a replicate mechanism in there somewhere.</p>
<p>Now, we can access our normal Rails modules through our connection modules. Magically of course.</p>
<pre>>> ActiveRecord::Base.active_connections.keys
=> []
>> Person.count
=> 2
>> ActiveRecord::Base.active_connections.keys
=> ["ActiveRecord::Base"]
>> DevelopmentClone1::Person.count
=> 0
>> ActiveRecord::Base.active_connections.keys
=> ["ActiveRecord::Base", "DevelopmentClone1::Person"]
</pre>
<p>Wowzers. <code>Person</code> <strong>and</strong> <code>DevelopmentClone1::Person</code> classes? </p>
<p>But note - <code>Person.count => 2</code> and <code>DevelopmentClone1::Person.count => 0</code> - they are accessing different databases. The same class definition <code>Person</code> is being used for multiple database connections. We never defined more <code>Person</code> classes. Just the standard default one in <code>app/models/person.rb</code>.</p>
<p>The <code>active_connections</code> result shows that <code>DevelopmentClone1::Person</code> has its own connection. Yet you never had to manually call <code>DevelopmentClone1::Person.establish_connection :development_clone1</code> - it was called automatically when the class is created.</p>
<p>Of course, <code>DevelopmentClone2::Person</code> is automatically connected to <code>:development_clone2</code>, and so on.</p>
<h2>Behind the scenes</h2>
<p>Let's look at our generated classes:</p>
<pre>$ ruby script/console
>> DevelopmentClone1::Person
=> DevelopmentClone1::Person
>> Person
=> Person
>> DevelopmentClone1::Person.superclass
=> Person
</pre>
<p>That is, there is a <code>DevelopmentClone1::Person</code> class, automagically generated for you, which is a subclass of <code>Person</code>, so it has all its behaviour etc.</p>
<h2>Dynamic connection pools within Rails controllers</h2>
<p>The magic of the <code>conn</code> method will now be revealed:</p>
<pre>$ ruby script/console
>> def conn
>>   @@connection_pool[rand(@@connection_pool.size)]
>> end
>> conn::Person.name
=> "DevelopmentClone2::Person"
>> conn::Person.name
=> "DevelopmentClone1::Person"
</pre>
<p>The <code>conn</code> method randomly returns one of the connection modules. Subsequently, <code>conn::Person</code> returns a Person class that is connected to a random clone database. Booya. Free Twitter swag coming my way.</p>
<p>Place the <code>conn</code> method in the ApplicationController class, and you can get dynamic connection pooling within Rails actions as needed, as in the following example (from the top of the article):</p>
<pre>class PeopleController < ApplicationController
  def index
    @people = conn::Person.find(:all)
  end
end
</pre>
<p>Decent Ruby-fu, I think. Certainly better than manually calling <code>establish_connection</code> on model classes before each call (or in a <code>before_filter</code> call, I guess).</p>
<h1>This is just a concept</h1>
<p>I know this tutorial above works. But that might be the extent of what I know. Let me know if this has any quirks (especially if you solve them), or if this is a stupid idea for implementing connection pooling with nice Ruby syntax.</p>
<p><strong>Hope it helps.</strong></p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2010/03/15/using-coffeescript-in-rails-and-even-on-heroku/' rel='bookmark' title='Permanent Link: Using CoffeeScript in Rails and even on Heroku'>Using CoffeeScript in Rails and even on Heroku</a> <small>I&#8217;m pretty excited about CoffeeScript as a clean-syntax replacement for...</small></li><li><a href='http://drnicwilliams.com/2009/11/03/first-look-at-rails-3-0-pre/' rel='bookmark' title='Permanent Link: First look at rails 3.0.pre'>First look at rails 3.0.pre</a> <small> This article is out of date in some aspects....</small></li><li><a href='http://drnicwilliams.com/2009/10/07/rails-themes-can-remember-things/' rel='bookmark' title='Permanent Link: Rails themes can remember things'>Rails themes can remember things</a> <small>I was getting annoyed at having to remember all the...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2007/04/12/magic-multi-connections-a-facility-in-rails-to-talk-to-more-than-one-database-at-a-time/feed/</wfw:commentRss>
		<slash:comments>68</slash:comments>
		</item>
		<item>
		<title>New magical version of Symbol.to_proc</title>
		<link>http://drnicwilliams.com/2006/09/28/new-magical-version-of-symbolto_proc/</link>
		<comments>http://drnicwilliams.com/2006/09/28/new-magical-version-of-symbolto_proc/#comments</comments>
		<pubDate>Thu, 28 Sep 2006 12:01:41 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[DSL]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[map_by_method]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/2006/09/28/new-magical-version-of-symbolto_proc/</guid>
		<description><![CDATA[Before the magic, let&#8217;s go through a Beginner&#8217;s Guide to Mapping, then Advanced Guide to Symbol.to_proc, and THEN, the magical version. Its worth it. Its sexy, nifty AND magical all at once. Beginner&#8217;s Guide to Mapping Need to invoke a method on each object in an array and return the result? # call 'to_i' on [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2007/08/12/map_by_method-now-works-with-activerecord-associations/' rel='bookmark' title='Permanent Link: map_by_method now works with ActiveRecord associations'>map_by_method now works with ActiveRecord associations</a> <small>I was always annoyed that map_by_method was broken for ActiveRecord...</small></li><li><a href='http://drnicwilliams.com/2007/07/23/magic-wiggly-lines-guessmethod-by-chris-shea/' rel='bookmark' title='Permanent Link: Magic Wiggly Lines => GuessMethod, by Chris Shea'>Magic Wiggly Lines => GuessMethod, by Chris Shea</a> <small>If you ever make time to code just for pleasure,...</small></li><li><a href='http://drnicwilliams.com/2007/04/12/magic-multi-connections-a-facility-in-rails-to-talk-to-more-than-one-database-at-a-time/' rel='bookmark' title='Permanent Link: Magic Multi-Connections: A &#8220;facility in Rails to talk to more than one database at a time&#8221;'>Magic Multi-Connections: A &#8220;facility in Rails to talk to more than one database at a time&#8221;</a> <small>At this point in time there’s no facility in Rails...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>Before the magic, let&#8217;s go through a <strong>Beginner&#8217;s Guide to Mapping</strong>, then <strong>Advanced Guide to Symbol.to_proc</strong>, and THEN, the <strong>magical version</strong>. Its worth it. Its sexy, nifty AND magical all at once.</p>
<h3>Beginner&#8217;s Guide to Mapping</h3>
<p>Need to invoke a method on each object in an array and return the result?</p>
<pre>
<span class="comments"># call 'to_i' on each item of the list to return the list of numbers</span>
>> list = ['1',  '2', '3']
=> ["1", "2", "3"]
>> <span class="constant">list.map {|item| item.to_i}</span>
=> [1, 2, 3]
</pre>
<p>That is, we called the <code>to_i</code> method on each item of the list, thus converting the 3 strings into 3 integers. Of course, we could have called any method on any set of objects.</p>
<h3>Advanced Guide to Symbol.to_proc</h3>
<p>After doing that a few times, you start wishing there was simpler syntax. Enter: Symbol.to_proc</p>
<pre>
>> list.map <span class="constant">&#038;:to_i</span>
=> [1, 2, 3]
</pre>
<p>It looks like magic. Well it certainly doesn&#8217;t make any sense. But it works. (The secret: the <code>:to_id</code> symbol is cast into a Proc object by the leading <code>&#038;</code>. That is, it calls the <code>to_proc</code> method on the symbol. Rest of <a href="http://blogs.pragprog.com/cgi-bin/pragdave.cgi/Tech/Ruby/ToProc.rdoc">explanation</a> <a href="http://www.sitepoint.com/blogs/2006/06/19/insta-block-with-symbolto_proc/">here</a>.)</p>
<h3>Magical version of Symbol.to_proc</h3>
<p>Quite frankly, that&#8217;s still a lot of syntax. Plus, I normally forget to added parentheses around the <code>&#038;:to_i</code>, and then latter I want to invoke another method on the result, so I need to add the parentheses which is a pain&#8230; anyway. I thought of something niftier and dare I say, more magical.</p>
<p>How about this syntax:</p>
<pre>
>> list.<span class="constant">to_is</span>
=> [1, 2, 3]
</pre>
<p>This syntax makes sense &#8211; <code>to_is</code> is the plural of <code>to_i</code> &#8211; its obvious you want the <code>to_i</code>&#8216;s of your list.</p>
<p><em>What&#8217;s happening here?</em>You pass the plural of the method name to the container and it invokes the singular of the method name upon the children using the <code>map</code> code above. Source is below.</p>
<p>More examples? Want to get the names of all the objects of a list? (assuming that each item in the list has a <code>name</code> method)</p>
<pre>
>> contacts.map {|contact| contact.name}
=> ['Dr Nic', 'Banjo', ...]
>> contacts.map &#038;:name
=> ['Dr Nic', 'Banjo', ...]
>> contacts.names
=> ['Dr Nic', 'Banjo', ...]
</pre>
<p>You pick your favourite. I love the last one.</p>
<p>Bonus examples:</p>
<pre>
>> (1..10).to_a.to_ss
=> ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
>> (1..10).to_a.days
=> [86400, 172800, 259200, 345600, 432000, 518400, 604800, 691200, 777600, 864000]
>> [2,'two', :two].classes
=> [Fixnum, String, Symbol]
>> [2,'two', :two].classes.names
=> ["Fixnum", "String", "Symbol"]
>> [2,'two', :two].classes.names.lengths
=> [6, 6, 6]
</pre>
<p>So much happy syntax in one place!</p>
<p>UPDATE: After conversation on <a href="http://www.ruby-forum.com/topic/82905">Ruby Forums</a>, we&#8217;ve come up with some new syntax:</p>
<pre>
>> (1..5).to_a.map_days
=> [86400, 172800, 259200, 345600, 432000]
>> list = [nil, 1, 2, nil, 4]
=> [nil, 1, 2, nil, 4]
>> list.reject_nil?
=> [1, 2, 4]
</pre>
<p>Neat.</p>
<h3>How do I do this at home?</h3>
<p>Download and include this <a href="http://drnicwilliams.com/wp-content/uploads/2006/09/generic_map_to_proc.rb">mini-library</a>. Source below. Have fun.</p>
<pre>
module GenericMapToProc
  def self.included(base)
    super

    base.module_eval <<-EOS
      def method_missing(method, *args, &#038;block)
        super
      rescue NoMethodError
        error = $!
        begin
          re = /(map|collect|select|each|reject)_([\\\\w\\\\_]+\\\\??)/
          if (match = method.to_s.match(re))
            iterator, callmethod = match[1..2]
            return self.send(iterator) {|item| item.send callmethod}
          end
          return self.map {|item| item.send method.to_s.singularize.to_sym}
        rescue NoMethodError
          nil
        end
        raise error
      end
    EOS
  end
end

unless String.instance_methods.include? "singularize"
  String.module_eval <<- EOS
    def singularize
      self.gsub(/e?s\Z/,'')
    end
  EOS
end

# Add this to the Array class
Array.send :include, GenericMapToProc
</pre>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2007/08/12/map_by_method-now-works-with-activerecord-associations/' rel='bookmark' title='Permanent Link: map_by_method now works with ActiveRecord associations'>map_by_method now works with ActiveRecord associations</a> <small>I was always annoyed that map_by_method was broken for ActiveRecord...</small></li><li><a href='http://drnicwilliams.com/2007/07/23/magic-wiggly-lines-guessmethod-by-chris-shea/' rel='bookmark' title='Permanent Link: Magic Wiggly Lines => GuessMethod, by Chris Shea'>Magic Wiggly Lines => GuessMethod, by Chris Shea</a> <small>If you ever make time to code just for pleasure,...</small></li><li><a href='http://drnicwilliams.com/2007/04/12/magic-multi-connections-a-facility-in-rails-to-talk-to-more-than-one-database-at-a-time/' rel='bookmark' title='Permanent Link: Magic Multi-Connections: A &#8220;facility in Rails to talk to more than one database at a time&#8221;'>Magic Multi-Connections: A &#8220;facility in Rails to talk to more than one database at a time&#8221;</a> <small>At this point in time there’s no facility in Rails...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2006/09/28/new-magical-version-of-symbolto_proc/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Turn-based game DSL</title>
		<link>http://drnicwilliams.com/2006/09/07/turn-based-game-dsl/</link>
		<comments>http://drnicwilliams.com/2006/09/07/turn-based-game-dsl/#comments</comments>
		<pubDate>Thu, 07 Sep 2006 09:28:17 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[BTS]]></category>
		<category><![CDATA[DSL]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/2006/09/07/turn-based-game-dsl/</guid>
		<description><![CDATA[Late in the night, whilst the baby feeds, I continue to develop Dr Nic&#8217;s Civilizations game. This led me to develop a DSL for the specification of game rules. You need to see this. Here&#8217;s an example definition of some terrain: class Desert < Terrain title "Desert" letter "d" graphic "desert" movement_cost 1 defense_bonus 10 [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2007/04/12/magic-multi-connections-a-facility-in-rails-to-talk-to-more-than-one-database-at-a-time/' rel='bookmark' title='Permanent Link: Magic Multi-Connections: A &#8220;facility in Rails to talk to more than one database at a time&#8221;'>Magic Multi-Connections: A &#8220;facility in Rails to talk to more than one database at a time&#8221;</a> <small>At this point in time there’s no facility in Rails...</small></li><li><a href='http://drnicwilliams.com/2006/11/20/coming-home-to-brisbane/' rel='bookmark' title='Permanent Link: Coming home to Brisbane'>Coming home to Brisbane</a> <small>I left Australia on the 3rd of July last year...</small></li><li><a href='http://drnicwilliams.com/2006/08/28/extending-_whys-creature-class/' rel='bookmark' title='Permanent Link: Extending _why&#8217;s Creature class'>Extending _why&#8217;s Creature class</a> <small>Many Rubist&#8217;s first explanation of metaprogramming is by why the...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>Late in the night, whilst the baby feeds, I continue to develop <strong>Dr Nic&#8217;s Civilizations</strong> game. This led me to develop a DSL for the specification of game rules. You need to see this.</p>
<p>Here&#8217;s an example definition of some terrain:</p>
<pre>
  class Desert < Terrain
    title           "Desert"
    letter          "d"
    graphic         "desert"
    movement_cost   1
    defense_bonus   10
    food            0
    shield          1
    trade           0
  end
  class Oasis < Desert
    title           "Oasis"
    special_code    1
    food            3
    shield          1
    trade           0
    graphic         "oasis"
  end
</pre>
<p>An Oasis is a special version of the Desert terrain, so Ruby subclasses offer a compatible relationship.</p>
<p>This is seriously cool. All in Ruby.</p>
<h3>Why write a DSL for something trite like game rules?</h3>
<p>The descriptions of terrain (plains, hills, ocean), the improvements (roads, irrigation, mines), etc. all need defining somewhere. Here are the standard options:</p>
<ol>
<li>Rows in a database, imported into ActiveRecords at startup</li>
<li>Files that are loaded at startup, parsed and converted into an internal data model</li>
<li>Ruby DSL</li>
</ol>
<p>The sort of configuration we're dealing with is static: its a part of the game design to a certain extent. Yes, I could put the configuration in a database and access/modify it via an <a href="http://trac.visualjquery.com/admin_console">admin console</a>, though version control becomes an additional administrative hassle.</p>
<p>Storing game rule configuration in external files makes version control trivial, though there is a one-time cost of implementing special purpose syntax, parsers, internal game data models and testing.</p>
<p>A Ruby DSL is exactly the same as implementing option 2 - the configuration is stored in files, though as the syntax is pure Ruby, there is no need to implement a parser and internal data model. </p>
<p>There was a one time cost for supporting the syntax. But <a href="http://redhanded.hobix.com/">why the lucky stiff</a> paid this cost for me with his <a href="http://poignantguide.net/ruby/chapter-6.html#section3">traits definition for slaying dragons</a> <a href="#game-dsl1">[1]</a>. So I was free and clear of any actual effort.</p>
<h3>"Yes, smart arse, but you still had to write up all those Ruby classes"</h3>
<p>An irrelevant argument, you'd have to enter the configuration for any of the 3 options, but...</p>
<p>I wrote a generator to build the Ruby class definitions for me from the <a href="http://www.freeciv.org/index.php">Freeciv</a>'s GPL rule sets. Sweet.</p>
<p><a name="game-dsl1">[1]</a> The definition of the <code>Terrain</code> class, using the <code>traits</code> mechanism, is simple:</p>
<pre>
  class <span class="constant">Terrain</span>
    <span class="string">traits</span> :title,
      :letter,
      :graphic,
      :movement_cost,
      :defense_bonus,
      :food,
      :shield,
      :trade,
      :special_code
  end
</pre>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2007/04/12/magic-multi-connections-a-facility-in-rails-to-talk-to-more-than-one-database-at-a-time/' rel='bookmark' title='Permanent Link: Magic Multi-Connections: A &#8220;facility in Rails to talk to more than one database at a time&#8221;'>Magic Multi-Connections: A &#8220;facility in Rails to talk to more than one database at a time&#8221;</a> <small>At this point in time there’s no facility in Rails...</small></li><li><a href='http://drnicwilliams.com/2006/11/20/coming-home-to-brisbane/' rel='bookmark' title='Permanent Link: Coming home to Brisbane'>Coming home to Brisbane</a> <small>I left Australia on the 3rd of July last year...</small></li><li><a href='http://drnicwilliams.com/2006/08/28/extending-_whys-creature-class/' rel='bookmark' title='Permanent Link: Extending _why&#8217;s Creature class'>Extending _why&#8217;s Creature class</a> <small>Many Rubist&#8217;s first explanation of metaprogramming is by why the...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2006/09/07/turn-based-game-dsl/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>[Trick] Natural language DSL in Ruby</title>
		<link>http://drnicwilliams.com/2006/09/04/trick-natural-language-dsl/</link>
		<comments>http://drnicwilliams.com/2006/09/04/trick-natural-language-dsl/#comments</comments>
		<pubDate>Mon, 04 Sep 2006 15:15:29 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[DSL]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Trick]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/2006/09/04/trick-natural-language-dsl/</guid>
		<description><![CDATA[Ever tried to explain DSLs (domain specific languages) to someone, so that they know how wonderful Ruby is, and just run out of useful examples? Try this piece of Street Magic on them&#8230; The effect See if your unsuspecting friend can figure out what this code will do. If they can, then say, &#8220;That&#8217;s because [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2010/06/01/validate-and-save-your-ruby-in-textmate-with-secret-rubinus-superpowers/' rel='bookmark' title='Permanent Link: Validate and Save your Ruby in TextMate &#8211; with secret Rubinus superpowers'>Validate and Save your Ruby in TextMate &#8211; with secret Rubinus superpowers</a> <small>In some TextMate bundles, if you save a file it...</small></li><li><a href='http://drnicwilliams.com/2008/12/11/future-proofing-your-ruby-code/' rel='bookmark' title='Permanent Link: Future proofing your Ruby code. Ruby 1.9.1 is coming.'>Future proofing your Ruby code. Ruby 1.9.1 is coming.</a> <small> Bugger. I&#8217;m a Ruby monogamist. I use the Ruby...</small></li><li><a href='http://drnicwilliams.com/2008/07/04/unit-testing-iphone-apps-with-ruby-rbiphonetest/' rel='bookmark' title='Permanent Link: Unit Testing iPhone apps with Ruby: rbiphonetest'>Unit Testing iPhone apps with Ruby: rbiphonetest</a> <small> Everything to love about Ruby: the concise, powerful language;...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>Ever tried to explain DSLs (domain specific languages) to someone, so that they know how wonderful Ruby is, and just run out of useful examples? Try this piece of Street Magic on them&#8230;</p>
<h2>The effect</h2>
<p>See if your unsuspecting friend can figure out what this code will do. If they can, then say, &#8220;That&#8217;s because you are a domain expert in English. Good for you. Now use Ruby you Java boy.&#8221;</p>
<pre>
>> I.say "<span class="string">I love the Ruby language</span>"
<span class="constant">You said, 'I love the Ruby language'</span>
</pre>
<p>Cool, yes? Yes.</p>
<h2>How this trick works</h2>
<p>To set this up for your unsuspecting Ruby noob, type the following into your console/irb:</p>
<pre>
>> class I; def self.say(text); puts "You said, '#{text}'"; end; end
=> nil
</pre>
<p>Now you have a constant <code>I</code> upon which you can call class methods. </p>
<p>In long hand, this is:</p>
<pre>
class I
  def self.say(text)
    puts "You said, '#{text}'"
  end
end
</pre>
<p>Create other pronoun classes, such as <code>You</code>, <code>Everyone</code>, etc and give them methods representing verbs, such as <code>say</code>, <code>said</code>, <code>want_to</code>. </p>
<p>For example,</p>
<pre>
class You
  def self.cannot(action, target)
    puts "Didn't your mother tell you never say never? Of course you can #{action} #{target}"
  end
end
</pre>
<p>Which delights us with:</p>
<pre>
>> You.cannot <span class="string">:learn</span>, "<span class="string">Ruby</span>"
<span class="constant">Didn't your mother tell you never say never? Of course you can learn Ruby</span>
</pre>
<h2>&#8220;I still don&#8217;t know what a DSL is&#8221;</h2>
<p>That&#8217;s unfortunate for you.</p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2010/06/01/validate-and-save-your-ruby-in-textmate-with-secret-rubinus-superpowers/' rel='bookmark' title='Permanent Link: Validate and Save your Ruby in TextMate &#8211; with secret Rubinus superpowers'>Validate and Save your Ruby in TextMate &#8211; with secret Rubinus superpowers</a> <small>In some TextMate bundles, if you save a file it...</small></li><li><a href='http://drnicwilliams.com/2008/12/11/future-proofing-your-ruby-code/' rel='bookmark' title='Permanent Link: Future proofing your Ruby code. Ruby 1.9.1 is coming.'>Future proofing your Ruby code. Ruby 1.9.1 is coming.</a> <small> Bugger. I&#8217;m a Ruby monogamist. I use the Ruby...</small></li><li><a href='http://drnicwilliams.com/2008/07/04/unit-testing-iphone-apps-with-ruby-rbiphonetest/' rel='bookmark' title='Permanent Link: Unit Testing iPhone apps with Ruby: rbiphonetest'>Unit Testing iPhone apps with Ruby: rbiphonetest</a> <small> Everything to love about Ruby: the concise, powerful language;...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2006/09/04/trick-natural-language-dsl/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>So, cattr_accessor doesn&#8217;t work like it should?</title>
		<link>http://drnicwilliams.com/2006/08/27/so-cattr_accessor-doesnt-work-like-it-should/</link>
		<comments>http://drnicwilliams.com/2006/08/27/so-cattr_accessor-doesnt-work-like-it-should/#comments</comments>
		<pubDate>Sun, 27 Aug 2006 15:59:20 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[BTS]]></category>
		<category><![CDATA[DSL]]></category>
		<category><![CDATA[Meta-Programming]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/2006/08/27/so-cattr_accessor-doesnt-work-like-it-should/</guid>
		<description><![CDATA[Rails&#8217; active_support library adds some wonderful functions into standard Ruby classes. Some we all use day-in-day out are attr_accessor and its class-level equivalent, cattr_accessor. But cattr_accessor doesn&#8217;t work the way you (read, &#8220;me&#8221;) thought at first glance when you use subclasses. I thought if I declared a class accessor in the superclass, then I would [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2007/04/12/magic-multi-connections-a-facility-in-rails-to-talk-to-more-than-one-database-at-a-time/' rel='bookmark' title='Permanent Link: Magic Multi-Connections: A &#8220;facility in Rails to talk to more than one database at a time&#8221;'>Magic Multi-Connections: A &#8220;facility in Rails to talk to more than one database at a time&#8221;</a> <small>At this point in time there’s no facility in Rails...</small></li><li><a href='http://drnicwilliams.com/2006/09/07/turn-based-game-dsl/' rel='bookmark' title='Permanent Link: Turn-based game DSL'>Turn-based game DSL</a> <small>Late in the night, whilst the baby feeds, I continue...</small></li><li><a href='http://drnicwilliams.com/2006/08/28/extending-_whys-creature-class/' rel='bookmark' title='Permanent Link: Extending _why&#8217;s Creature class'>Extending _why&#8217;s Creature class</a> <small>Many Rubist&#8217;s first explanation of metaprogramming is by why the...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>Rails&#8217; <code>active_support</code> library adds some wonderful functions into standard Ruby classes. Some we all use day-in-day out are <code>attr_accessor</code> and its class-level equivalent, <code>cattr_accessor</code>.</p>
<p>But <code>cattr_accessor</code> doesn&#8217;t work the way you (read, &#8220;me&#8221;) thought at first glance when you use subclasses. I thought if I declared a class accessor in the superclass, then I would have independent class attributes for all my subclasses. Apparently not&#8230;</p>
<pre>
>> class Parent; <strong>cattr_accessor</strong> :val; end
=> [:val]
>> class Child1 < Parent; end
=> nil
>> class Child2 < Parent; end
=> nil
>> Child1.val = 4
=> 4
>> Child2.val
=> 4
>> Child2.val = 5
=> 5
>> Child1.val
=> 5
</pre>
<p><code>Child1.val</code> and <code>Child2.val</code> seem to be the same value. Not very independent at all. Internally, the classes share a common class attribute. This is useful in certain circumstances, but not what I was looking for.</p>
<p>Instead, I found <code>class_inheritable_accessor</code>.</p>
<pre>
>> class Parent; <strong>class_inheritable_accessor</strong> :val; end
=> [:val]
>> class Child1 < Parent; end
=> nil
>> class Child2 < Parent; end
=> nil
>> Child1.val = 4
=> 4
>> Child2.val = 4
=> 4
>> Child2.val = 5
=> 5
>> Child1.val
=> 4
</pre>
<p>Lovely. Each subclass will have an independent value once you&#8217;ve assigned it a value explicitly, else it will pick up the value from its superclass.</p>
<p>UPDATE: <code>class_inheritable_accessor</code> and co. actually clone the superclass&#8217;s inherited attributes, rather than just referencing them.</p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2007/04/12/magic-multi-connections-a-facility-in-rails-to-talk-to-more-than-one-database-at-a-time/' rel='bookmark' title='Permanent Link: Magic Multi-Connections: A &#8220;facility in Rails to talk to more than one database at a time&#8221;'>Magic Multi-Connections: A &#8220;facility in Rails to talk to more than one database at a time&#8221;</a> <small>At this point in time there’s no facility in Rails...</small></li><li><a href='http://drnicwilliams.com/2006/09/07/turn-based-game-dsl/' rel='bookmark' title='Permanent Link: Turn-based game DSL'>Turn-based game DSL</a> <small>Late in the night, whilst the baby feeds, I continue...</small></li><li><a href='http://drnicwilliams.com/2006/08/28/extending-_whys-creature-class/' rel='bookmark' title='Permanent Link: Extending _why&#8217;s Creature class'>Extending _why&#8217;s Creature class</a> <small>Many Rubist&#8217;s first explanation of metaprogramming is by why the...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2006/08/27/so-cattr_accessor-doesnt-work-like-it-should/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
