<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/atom10full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US">
  <id>http://blog.tracefunc.com</id>
  <link type="text/html" href="http://blog.tracefunc.com" rel="alternate" />
  <title>set_trace_func</title>
  <updated />
    <link rel="self" href="http://feeds.feedburner.com/set_trace_func" type="application/atom+xml" /><entry>
    <id>tag:blog.tracefunc.com,2008-01-22:8aae59459b898828fefd6ce2be447634</id>
    <link type="text/html" href="http://blog.tracefunc.com/2008/07/16/specing-layouts" rel="alternate" />
    <title>Specing Layouts</title>
    <updated>2008-07-16T16:37:19UTC</updated>
    <author>
      
      
    </author>
    <content type="html">&lt;p&gt;Just a quick little snippet for those trying to write specs for their layout.&lt;/p&gt;

&lt;p&gt;Create your spec in &lt;code&gt;spec/views/layout/application.html.erb_spec.html&lt;/code&gt;, and add this class to it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Layout &amp;lt; Application
  layout nil
  def application; render; end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then just test it as you would any other ordinary view.&lt;/p&gt;
    &lt;div class="extended" id="more_41"&gt;
    
    &lt;/div&gt;</content>
  </entry>

  <entry>
    <id>tag:blog.tracefunc.com,2008-01-22:e31449de98962872bc5de5817c506f31</id>
    <link type="text/html" href="http://blog.tracefunc.com/2008/07/15/porting-rails-plugins-to-datamapper" rel="alternate" />
    <title>Porting Rails Plugins to DataMapper</title>
    <updated>2008-07-15T15:59:17UTC</updated>
    <author>
      
      
    </author>
    <content type="html">&lt;p&gt;As a follow-up to my &lt;a href="http://blog.tracefunc.com/2008/07/15/porting-rails-plugins-to-merb"&gt;previous post&lt;/a&gt;, here's some gotchas to be aware of if you're looking to support both ActiveRecord and DataMapper in a Merb (and/or Rails) plugin.&lt;/p&gt;

&lt;h2&gt;The Strategy&lt;/h2&gt;

&lt;p&gt;The best way I've found to handle multiple ORM support in your plugin is not to start monkeypatching around to make one ORM handle like another.  I've done it, and can tell you that wrapping one ORM's backend into another is &lt;a href="http://pastie.org/233178"&gt;ugly&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The better way is to localize the points where your plugin interacts with the data model, with an eye to swapping them out.  For the above example, I would be better off taking the method that &lt;em&gt;used&lt;/em&gt; the reflection method and putting it inside an ActiveRecord-specific module.  Then, create a DataMapper-specific module that defines the same method, but instead relies on the DM backend to get at the association information.  Finally, when the plugin was loaded I could just include one of the modules based on which ORM was loaded into the runtime.&lt;/p&gt;

&lt;h2&gt;Basic Translation&lt;/h2&gt;

&lt;p&gt;Now that we have a plan, we can start translating our extracted functions from AR bits to DM bits.  There's a bunch of fairly straightforward transformations we can make.&lt;/p&gt;

&lt;p&gt;It's unfortunate that there isn't more unity between the two, as from a library-developer's perspective it would make this sort of thing much easier, but the DM team is pretty vocal about wanting the best API they can get, and not worrying about being hobbled by how AR does things.  I don't particularly disagree.&lt;/p&gt;

&lt;table&gt;
  &lt;tr&gt;&lt;td&gt;ActiveRecord&lt;/td&gt;&lt;td&gt;DataMapper&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;.find(:all, ...)   &lt;/td&gt;&lt;td&gt;.all(...)         &lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;.find(:first, ...) &lt;/td&gt;&lt;td&gt;.first(...)       &lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;.find(id)          &lt;/td&gt;&lt;td&gt;.get(...)         &lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;.find_all_by_id(id)&lt;/td&gt;&lt;td&gt;.all(:id =&gt; ids)  &lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;.table_name        &lt;/td&gt;&lt;td&gt;.storage_name     &lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;.primary_key       &lt;/td&gt;&lt;td&gt;.key.first.name   &lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;.connection        &lt;/td&gt;&lt;td&gt;repository.adapter&lt;/td&gt;&lt;/tr&gt;

  &lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;h2&gt;Raw SQL&lt;/h2&gt;

&lt;p&gt;If you're running raw SQL queries, firstly, I'm sorry.  Secondly, you want to run &lt;code&gt;.query&lt;/code&gt; instead of &lt;code&gt;.execute&lt;/code&gt;.  Thirdly, if you care about getting the results of the query back, AR returns an array of arrays, DM returns an array of hashlike objects, so you want to map them for their values array.  The hashlike object in question is order-preserving, so you'll get things out in the right order.  If you're concerned, grab one of the result objects and verify that the keys array is in the correct order.&lt;/p&gt;

&lt;h2&gt;Hooks&lt;/h2&gt;

&lt;p&gt;ActiveRecord defines a few hook points, along the lines of &lt;code&gt;before_create&lt;/code&gt; and &lt;code&gt;after_save&lt;/code&gt;.  DataMapper uses (a modified version of) the Extlib gem, allowing it to hook pretty much any method.  The syntax is like &lt;code&gt;before(:create)&lt;/code&gt; and &lt;code&gt;after(:save)&lt;/code&gt;.  AR's hooks pass in the object to work with, DM's have the object available as &lt;code&gt;self&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In before hooks, the AR hook chain stops if your method returns false, in DM you must &lt;code&gt;throw :halt&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;Things You Shouldn't Be Doing Anyways&lt;/h2&gt;

&lt;p&gt;If you're manually setting &lt;code&gt;@attribute&lt;/code&gt; values in your AR code, you'll need to use &lt;code&gt;instance_variable_set&lt;/code&gt; for DataMapper.  I recommend writing manual accessor methods to wrap it for abstraction.&lt;/p&gt;

&lt;p&gt;If you're wanting some arbitrary data structures back, I recommend using OpenStruct (&lt;code&gt;require 'ostruct'&lt;/code&gt;) to pass structured data back and forth.  This was especially handy when I wanted some results from DM to look like AR, because I was just doing an adapter (bad me!) and the client code wanted to interact with the AR object.  Just be aware that OpenStruct doesn't quite clear out all its methods, so you might want to define some custom readers anyway.  I had problems with &lt;code&gt;type&lt;/code&gt; in particular, which is a deprecated alias of &lt;code&gt;class&lt;/code&gt; - redefining the method to return &lt;code&gt;@table[:type]&lt;/code&gt; fixed that up nicely.&lt;/p&gt;
    &lt;div class="extended" id="more_40"&gt;
    
    &lt;/div&gt;</content>
  </entry>

  <entry>
    <id>tag:blog.tracefunc.com,2008-01-22:ef4130f03b7aa53ba1f047dd3616e2bd</id>
    <link type="text/html" href="http://blog.tracefunc.com/2008/07/15/porting-rails-plugins-to-merb" rel="alternate" />
    <title>Porting Rails Plugins to Merb</title>
    <updated>2008-07-15T00:55:26UTC</updated>
    <author>
      
      
    </author>
    <content type="html">&lt;p&gt;We're about to start up a new project at work, and we've decided to go with &lt;a href="http://merbivore.com/"&gt;Merb&lt;/a&gt; (yay!) rather than &lt;a href="http://rubyonrails.com/"&gt;Rails&lt;/a&gt;. Before we get started, though, we wanted to make sure that we'd be able to integrate well with the various plugins available for Rails.&lt;/p&gt;

&lt;p&gt;The first two libraries we wanted to use were &lt;a href="http://github.com/fauna/ultrasphinx/"&gt;ultrasphinx&lt;/a&gt;, an interface to the &lt;a href="http://sphinxsearch.com/"&gt;Sphinx&lt;/a&gt; fulltext search engine, and &lt;a href="http://github.com/kr/async-observer/"&gt;async-observer&lt;/a&gt;, an abstraction library using the &lt;a href="http://xph.us/software/beanstalkd/"&gt;beanstalkd&lt;/a&gt; work queue library to delay actions to be processed at a later time, rather than while processing the page.&lt;/p&gt;

&lt;p&gt;The good news is that both of the projects are available on GitHub, which means easy forks, and easy contributions back to the source if my changes are as good as I think they are.&lt;/p&gt;

&lt;p&gt;So, today I'd like to talk about the basic changes you'll need to make to a Rails plugin so that it will play nicely with Merb, and a few of the extra hooks that come into play.  In the near future, I hope to provide a bit of a primer on adapting a plugin that uses ActiveRecord so that it will also work with Datamapper.  Preview tip from that post, if you're calling any methods provided by ActiveRecord, &lt;em&gt;please&lt;/em&gt; make an adapter class/module to pass those methods through, as it makes ports like these &lt;em&gt;much&lt;/em&gt; easier.&lt;/p&gt;

&lt;h2&gt;Basics&lt;/h2&gt;

&lt;p&gt;To get your plugin to get picked up properly, Rails requires an &lt;code&gt;init.rb&lt;/code&gt; file in the plugin root.  The equivalent for Merb is a file named after your plugin, in the &lt;code&gt;/lib&lt;/code&gt; directory.  Copying &lt;code&gt;/init.rb&lt;/code&gt; to &lt;code&gt;/lib/async_observer.rb&lt;/code&gt; worked for that one, Ultrasphinx is somewhat better behaved in that its init.rb just required ultrasphinx, so both Rails and Merb worked for me out of the box.&lt;/p&gt;

&lt;p&gt;If you depend on anything in Merb, you'll need to add to the docs that applications should add the plugin dependency inside a &lt;code&gt;Merb::BootLoader.before_app_loads&lt;/code&gt; block - otherwise nothing in Merb is defined yet.  This is of particular importance if you want to switch behaviour based on whether the Rails or Merb constants are defined.  As Rails handles loading plugins itself, there's no concern for keeping things special for Rails.&lt;/p&gt;

&lt;p&gt;If you plan on dealing with the app directory structure or environment, an easy way to do it is:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if defined?(Rails)
  ROOT = RAILS_ROOT
  ENV = RAILS_ENV
elsif defined?(Merb)
  ROOT = Merb.root
  ENV = (Merb.env == 'rake' ? 'development' : Merb.env)
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The additional rake environment transparently proxies to the development db connection, so if you just want to compare your plugin's interpretation of &lt;code&gt;ENV&lt;/code&gt; the above will make that cleaner.&lt;/p&gt;

&lt;h2&gt;Rake Tasks&lt;/h2&gt;

&lt;p&gt;Rails automatically loads any files matching &lt;code&gt;tasks/*.rake&lt;/code&gt; in the plugin dir.&lt;/p&gt;

&lt;p&gt;Merb needs to be told explicitly, relative to the lib directory.  The canonical example from the docs is:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if defined?(Merb::Plugins)
  Merb::Plugins.add_rakefiles "merb_sequel" / "merbtasks"
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Unfortunately, it seems that it wants specified a single file with a &lt;code&gt;.rb&lt;/code&gt; extension, which is incompatible with the Rails Way.  The easiest fix I've found is to add a file called &lt;code&gt;tasks.rb&lt;/code&gt; under &lt;code&gt;/lib&lt;/code&gt;, inside which you just manually require the individual rake files:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;load File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'tasks', 'merb_sequel.rake'))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Do note that the &lt;code&gt;load&lt;/code&gt; is necessary, &lt;code&gt;require&lt;/code&gt; doesn't pick the file up properly.&lt;/p&gt;

&lt;p&gt;Finally, if you have any tasks that depend on environment, the easiest way to get compatability with both frameworks is to add &lt;code&gt;task :environment =&amp;gt; :merb_env&lt;/code&gt; to your &lt;code&gt;merbtasks.rb&lt;/code&gt; file.&lt;/p&gt;

&lt;h2&gt;Generators&lt;/h2&gt;

&lt;p&gt;I haven't looked into generators in too much depth, but the API between Rails::Generator::Base and Merb::GeneratorBase seem different enough to warrant not reusing the generation script.  If you conditionally define a generator based on the &lt;code&gt;defined?&lt;/code&gt;ness of those two base classes, you should be able to reuse all your generation templates, and both Rails and Merb look in the same place for generators, so that should be the only adaptation necessary.&lt;/p&gt;

&lt;h2&gt;ORM Integration&lt;/h2&gt;

&lt;p&gt;Check back next time, as I write up my experience writing an ActiveRecord shim for the latest DataMapper.  It's vaguely ugly.  I &lt;em&gt;highly&lt;/em&gt; recommend if you're working on a plugin now that interacts with models to abstract any access to the database into a module, and include it appropriately.  This goes double if you're using any AR magic ;)&lt;/p&gt;
    &lt;div class="extended" id="more_38"&gt;
    
    &lt;/div&gt;</content>
  </entry>

  <entry>
    <id>tag:blog.tracefunc.com,2008-01-22:2e7b63e001184354332bf58a8e2f362d</id>
    <link type="text/html" href="http://blog.tracefunc.com/2008/07/14/two-questions" rel="alternate" />
    <title>Two Questions</title>
    <updated>2008-07-14T17:54:57UTC</updated>
    <author>
      
      
    </author>
    <content type="html">&lt;p&gt;&lt;strong&gt;Question #1:&lt;/strong&gt; Why is Symbol#to_proc so popular?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Array
  alias old_map map

  def map(method=nil, *args, &amp;amp;blk)
    return old_each(&amp;amp;blk) if block_given?
    old_map do |e|
      e.send(method, *args)
    end
  end
end

ary = %w(hello world)
puts ary.map(:reverse).join(" ")
puts ary.map(:*, 2).join(" ")
puts ary.map(:slice, 1, 3).join(" ")
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It should be trivial to do this for the other common enumerable methods, the only places I see Symbol#to_proc used, anyway.&lt;/p&gt;

&lt;p&gt;I posit that the answer is question 2.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question #2:&lt;/strong&gt; Why do I need to do this method hackery in Array instead of Enumerable?  I can understand Array having its own definitions of the standard collection methods for performance reasons, but in a properly OO system, that should be transparent to me.&lt;/p&gt;
    &lt;div class="extended" id="more_39"&gt;
    
    &lt;/div&gt;</content>
  </entry>

  <entry>
    <id>tag:blog.tracefunc.com,2008-01-22:ca50390a05e12fef4201113a41814bbb</id>
    <link type="text/html" href="http://blog.tracefunc.com/2008/07/11/embedding-gems-in-merb" rel="alternate" />
    <title>Embedding Gems in Merb</title>
    <updated>2008-07-11T18:53:00UTC</updated>
    <author>
      
      
    </author>
    <content type="html">&lt;p&gt;Daniel Manges did up instructions on &lt;a href="http://www.dcmanges.com/blog/rails-first-class-vendor-gems"&gt;storing explicit versions of gems in your rails app&lt;/a&gt;.  If instead you're using merb, you probably want to do that too, as it makes for much easier deploys.&lt;/p&gt;

&lt;p&gt;Thankfully, it's much less pain in merb:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gem install async-observer -i gems
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;-i&lt;/code&gt; option tells rubygems to install the gems to that directory, and when you require the gem from inside merb, it will look in the local gems directory first, and find yours.&lt;/p&gt;

&lt;p&gt;Optionally, you can skip generating docs by adding &lt;code&gt;--no-rdoc --no-ri&lt;/code&gt; to the line, and depending on what you're installing, you may want to &lt;code&gt;--ignore-dependencies&lt;/code&gt; as well.&lt;/p&gt;

&lt;p&gt;If the gem in question builds a binary extension, you may be out of luck if you try to deploy it to a different architecture.&lt;/p&gt;

&lt;p&gt;The only problem I've found so far is that &lt;code&gt;gem cleanup&lt;/code&gt; won't accept a directory to clean, so you'll need to manually remove individual gems when you upgrade:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gem uninstall -i async-observer
&lt;/code&gt;&lt;/pre&gt;
    &lt;div class="extended" id="more_33"&gt;
    
    &lt;/div&gt;</content>
  </entry>

</feed>
