mirror of
https://github.com/kennethreitz-archive/kennethreitz.github.com.git
synced 2026-06-05 23:40:17 +00:00
69 lines
28 KiB
HTML
69 lines
28 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
|
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
|
|
<head>
|
|
<title>code.kennethreitz.com :: Syntax Highlighting Debug</title>
|
|
<link href='/stylesheets/screen.css' media='screen, projection' rel='stylesheet' type='text/css' />
|
|
<script src='http://ajax.googleapis.com/ajax/libs/mootools/1.2.4/mootools-yui-compressed.js' type='text/javascript'></script>
|
|
<script src='/javascripts/mootools-1.2.4.2-more.js' type='text/javascript'></script>
|
|
<script type='text/javascript'>
|
|
//<![CDATA[
|
|
var twitter_user = "kennethreitz"
|
|
var show_replies = false;
|
|
var tweet_count = 3;
|
|
//]]>
|
|
</script>
|
|
<script src='/javascripts/octopress.js' type='text/javascript'></script>
|
|
<script src='/javascripts/twitter.js' type='text/javascript'></script>
|
|
<link href='/atom.xml' rel='alternate' title='code.kennethreitz.com' type='application/atom+xml' />
|
|
</head>
|
|
<body id="">
|
|
<div id="header">
|
|
<div class='content'>
|
|
<h1>
|
|
<a class='title' href='/'>code.kennethreitz.com</a>
|
|
</h1>
|
|
</div>
|
|
</div>
|
|
<div id="nav">
|
|
<div class='content'>
|
|
<ul>
|
|
<li class='alpha'>
|
|
<a href='/'>Blog</a>
|
|
</li>
|
|
<li class='omega'>
|
|
<a href='/about.html'>About</a>
|
|
</li>
|
|
<li class='subscribe'>
|
|
<a href='/atom.xml'>Subscribe</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div id="page">
|
|
<div id="content">
|
|
<div id="main">
|
|
<div class="content"><div class="code_window">
<em>Ruby</em>
<div class="highlight"><pre><span class="k">def</span> <span class="nf">rebuild_site</span><span class="p">(</span><span class="n">relative</span><span class="p">)</span>
 <span class="nb">puts</span> <span class="s2">">>> Change Detected to: </span><span class="si">#{</span><span class="n">relative</span><span class="si">}</span><span class="s2"> <<<"</span>
 <span class="no">IO</span><span class="o">.</span><span class="n">popen</span><span class="p">(</span><span class="s1">'rake generate'</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">io</span><span class="o">|</span>
 <span class="nb">print</span><span class="p">(</span><span class="n">io</span><span class="o">.</span><span class="n">readpartial</span><span class="p">(</span><span class="mi">512</span><span class="p">))</span> <span class="k">until</span> <span class="n">io</span><span class="o">.</span><span class="n">eof?</span>
 <span class="k">end</span>
 <span class="nb">puts</span> <span class="s1">'>>> Update Complete <<<'</span>
<span class="k">end</span>
</pre>
</div>
</div>


<p>So that’s a small example. What about a big one?</p>

<div class="code_window">
<em>Ruby</em>
<div class="highlight"><pre><span class="nb">require</span> <span class="s1">'active_support/core_ext/array'</span>
<span class="nb">require</span> <span class="s1">'active_support/core_ext/hash/except'</span>
<span class="nb">require</span> <span class="s1">'active_support/core_ext/object/metaclass'</span>

<span class="k">module</span> <span class="nn">ActiveRecord</span>
 <span class="k">module</span> <span class="nn">NamedScope</span>
 <span class="kp">extend</span> <span class="no">ActiveSupport</span><span class="o">::</span><span class="no">Concern</span>

 <span class="c1"># All subclasses of ActiveRecord::Base have one named scope:</span>
 <span class="c1"># * <tt>scoped</tt> - which allows for the creation of anonymous \scopes, on the fly: <tt>Shirt.scoped(:conditions => {:color => 'red'}).scoped(:include => :washing_instructions)</tt></span>
 <span class="c1">#</span>
 <span class="c1"># These anonymous \scopes tend to be useful when procedurally generating complex queries, where passing</span>
 <span class="c1"># intermediate values (scopes) around as first-class objects is convenient.</span>
 <span class="c1">#</span>
 <span class="c1"># You can define a scope that applies to all finders using ActiveRecord::Base.default_scope.</span>
 <span class="n">included</span> <span class="k">do</span>
 <span class="n">named_scope</span> <span class="ss">:scoped</span><span class="p">,</span> <span class="nb">lambda</span> <span class="p">{</span> <span class="o">|</span><span class="n">scope</span><span class="o">|</span> <span class="n">scope</span> <span class="p">}</span>
 <span class="k">end</span>

 <span class="k">module</span> <span class="nn">ClassMethods</span>
 <span class="k">def</span> <span class="nf">scopes</span>
 <span class="n">read_inheritable_attribute</span><span class="p">(</span><span class="ss">:scopes</span><span class="p">)</span> <span class="o">||</span> <span class="n">write_inheritable_attribute</span><span class="p">(</span><span class="ss">:scopes</span><span class="p">,</span> <span class="p">{})</span>
 <span class="k">end</span>

 <span class="c1"># Adds a class method for retrieving and querying objects. A scope represents a narrowing of a database query,</span>
 <span class="c1"># such as <tt>:conditions => {:color => :red}, :select => 'shirts.*', :include => :washing_instructions</tt>.</span>
 <span class="c1">#</span>
 <span class="c1"># class Shirt < ActiveRecord::Base</span>
 <span class="c1"># named_scope :red, :conditions => {:color => 'red'}</span>
 <span class="c1"># named_scope :dry_clean_only, :joins => :washing_instructions, :conditions => ['washing_instructions.dry_clean_only = ?', true]</span>
 <span class="c1"># end</span>
 <span class="c1"># </span>
 <span class="c1"># The above calls to <tt>named_scope</tt> define class methods Shirt.red and Shirt.dry_clean_only. Shirt.red, </span>
 <span class="c1"># in effect, represents the query <tt>Shirt.find(:all, :conditions => {:color => 'red'})</tt>.</span>
 <span class="c1">#</span>
 <span class="c1"># Unlike <tt>Shirt.find(...)</tt>, however, the object returned by Shirt.red is not an Array; it resembles the association object</span>
 <span class="c1"># constructed by a <tt>has_many</tt> declaration. For instance, you can invoke <tt>Shirt.red.find(:first)</tt>, <tt>Shirt.red.count</tt>,</span>
 <span class="c1"># <tt>Shirt.red.find(:all, :conditions => {:size => 'small'})</tt>. Also, just</span>
 <span class="c1"># as with the association objects, named \scopes act like an Array, implementing Enumerable; <tt>Shirt.red.each(&block)</tt>,</span>
 <span class="c1"># <tt>Shirt.red.first</tt>, and <tt>Shirt.red.inject(memo, &block)</tt> all behave as if Shirt.red really was an Array.</span>
 <span class="c1">#</span>
 <span class="c1"># These named \scopes are composable. For instance, <tt>Shirt.red.dry_clean_only</tt> will produce all shirts that are both red and dry clean only.</span>
 <span class="c1"># Nested finds and calculations also work with these compositions: <tt>Shirt.red.dry_clean_only.count</tt> returns the number of garments</span>
 <span class="c1"># for which these criteria obtain. Similarly with <tt>Shirt.red.dry_clean_only.average(:thread_count)</tt>.</span>
 <span class="c1">#</span>
 <span class="c1"># All \scopes are available as class methods on the ActiveRecord::Base descendant upon which the \scopes were defined. But they are also available to</span>
 <span class="c1"># <tt>has_many</tt> associations. If,</span>
 <span class="c1">#</span>
 <span class="c1"># class Person < ActiveRecord::Base</span>
 <span class="c1"># has_many :shirts</span>
 <span class="c1"># end</span>
 <span class="c1">#</span>
 <span class="c1"># then <tt>elton.shirts.red.dry_clean_only</tt> will return all of Elton's red, dry clean</span>
 <span class="c1"># only shirts.</span>
 <span class="c1">#</span>
 <span class="c1"># Named \scopes can also be procedural:</span>
 <span class="c1">#</span>
 <span class="c1"># class Shirt < ActiveRecord::Base</span>
 <span class="c1"># named_scope :colored, lambda { |color|</span>
 <span class="c1"># { :conditions => { :color => color } }</span>
 <span class="c1"># }</span>
 <span class="c1"># end</span>
 <span class="c1">#</span>
 <span class="c1"># In this example, <tt>Shirt.colored('puce')</tt> finds all puce shirts.</span>
 <span class="c1">#</span>
 <span class="c1"># Named \scopes can also have extensions, just as with <tt>has_many</tt> declarations:</span>
 <span class="c1">#</span>
 <span class="c1"># class Shirt < ActiveRecord::Base</span>
 <span class="c1"># named_scope :red, :conditions => {:color => 'red'} do</span>
 <span class="c1"># def dom_id</span>
 <span class="c1"># 'red_shirts'</span>
 <span class="c1"># end</span>
 <span class="c1"># end</span>
 <span class="c1"># end</span>
 <span class="c1">#</span>
 <span class="c1">#</span>
 <span class="c1"># For testing complex named \scopes, you can examine the scoping options using the</span>
 <span class="c1"># <tt>proxy_options</tt> method on the proxy itself.</span>
 <span class="c1">#</span>
 <span class="c1"># class Shirt < ActiveRecord::Base</span>
 <span class="c1"># named_scope :colored, lambda { |color|</span>
 <span class="c1"># { :conditions => { :color => color } }</span>
 <span class="c1"># }</span>
 <span class="c1"># end</span>
 <span class="c1">#</span>
 <span class="c1"># expected_options = { :conditions => { :colored => 'red' } }</span>
 <span class="c1"># assert_equal expected_options, Shirt.colored('red').proxy_options</span>
 <span class="k">def</span> <span class="nf">named_scope</span><span class="p">(</span><span class="nb">name</span><span class="p">,</span> <span class="n">options</span> <span class="o">=</span> <span class="p">{},</span> <span class="o">&</span><span class="n">block</span><span class="p">)</span>
 <span class="nb">name</span> <span class="o">=</span> <span class="nb">name</span><span class="o">.</span><span class="n">to_sym</span>
 <span class="n">scopes</span><span class="o">[</span><span class="nb">name</span><span class="o">]</span> <span class="o">=</span> <span class="nb">lambda</span> <span class="k">do</span> <span class="o">|</span><span class="n">parent_scope</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="o">|</span>
 <span class="no">Scope</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">parent_scope</span><span class="p">,</span> <span class="k">case</span> <span class="n">options</span>
 <span class="k">when</span> <span class="no">Hash</span>
 <span class="n">options</span>
 <span class="k">when</span> <span class="no">Proc</span>
 <span class="n">options</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
 <span class="k">end</span><span class="p">,</span> <span class="o">&</span><span class="n">block</span><span class="p">)</span>
 <span class="k">end</span>
 <span class="n">metaclass</span><span class="o">.</span><span class="n">instance_eval</span> <span class="k">do</span>
 <span class="n">define_method</span> <span class="nb">name</span> <span class="k">do</span> <span class="o">|*</span><span class="n">args</span><span class="o">|</span>
 <span class="n">scopes</span><span class="o">[</span><span class="nb">name</span><span class="o">].</span><span class="n">call</span><span class="p">(</span><span class="nb">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">)</span>
 <span class="k">end</span>
 <span class="k">end</span>
 <span class="k">end</span>
 <span class="k">end</span>

 <span class="k">class</span> <span class="nc">Scope</span>
 <span class="kp">attr_reader</span> <span class="ss">:proxy_scope</span><span class="p">,</span> <span class="ss">:proxy_options</span><span class="p">,</span> <span class="ss">:current_scoped_methods_when_defined</span>
 <span class="no">NON_DELEGATE_METHODS</span> <span class="o">=</span> <span class="sx">%w(nil? send object_id class extend find size count sum average maximum minimum paginate first last empty? any? many? respond_to?)</span><span class="o">.</span><span class="n">to_set</span>
 <span class="o">[].</span><span class="n">methods</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">m</span><span class="o">|</span>
 <span class="k">unless</span> <span class="n">m</span> <span class="o">=~</span> <span class="sr">/^__/</span> <span class="o">||</span> <span class="no">NON_DELEGATE_METHODS</span><span class="o">.</span><span class="n">include?</span><span class="p">(</span><span class="n">m</span><span class="o">.</span><span class="n">to_s</span><span class="p">)</span>
 <span class="n">delegate</span> <span class="n">m</span><span class="p">,</span> <span class="ss">:to</span> <span class="o">=></span> <span class="ss">:proxy_found</span>
 <span class="k">end</span>
 <span class="k">end</span>

 <span class="n">delegate</span> <span class="ss">:scopes</span><span class="p">,</span> <span class="ss">:with_scope</span><span class="p">,</span> <span class="ss">:scoped_methods</span><span class="p">,</span> <span class="ss">:to</span> <span class="o">=></span> <span class="ss">:proxy_scope</span>

 <span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">proxy_scope</span><span class="p">,</span> <span class="n">options</span><span class="p">,</span> <span class="o">&</span><span class="n">block</span><span class="p">)</span>
 <span class="n">options</span> <span class="o">||=</span> <span class="p">{}</span>
 <span class="o">[</span><span class="n">options</span><span class="o">[</span><span class="ss">:extend</span><span class="o">]].</span><span class="n">flatten</span><span class="o">.</span><span class="n">each</span> <span class="p">{</span> <span class="o">|</span><span class="n">extension</span><span class="o">|</span> <span class="kp">extend</span> <span class="n">extension</span> <span class="p">}</span> <span class="k">if</span> <span class="n">options</span><span class="o">[</span><span class="ss">:extend</span><span class="o">]</span>
 <span class="kp">extend</span> <span class="no">Module</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="o">&</span><span class="n">block</span><span class="p">)</span> <span class="k">if</span> <span class="nb">block_given?</span>
 <span class="k">unless</span> <span class="no">Scope</span> <span class="o">===</span> <span class="n">proxy_scope</span>
 <span class="vi">@current_scoped_methods_when_defined</span> <span class="o">=</span> <span class="n">proxy_scope</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="ss">:current_scoped_methods</span><span class="p">)</span>
 <span class="k">end</span>
 <span class="vi">@proxy_scope</span><span class="p">,</span> <span class="vi">@proxy_options</span> <span class="o">=</span> <span class="n">proxy_scope</span><span class="p">,</span> <span class="n">options</span><span class="o">.</span><span class="n">except</span><span class="p">(</span><span class="ss">:extend</span><span class="p">)</span>
 <span class="k">end</span>

 <span class="k">def</span> <span class="nf">reload</span>
 <span class="n">load_found</span><span class="p">;</span> <span class="nb">self</span>
 <span class="k">end</span>

 <span class="k">def</span> <span class="nf">first</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
 <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">first</span><span class="o">.</span><span class="n">kind_of?</span><span class="p">(</span><span class="nb">Integer</span><span class="p">)</span> <span class="o">||</span> <span class="p">(</span><span class="vi">@found</span> <span class="o">&&</span> <span class="o">!</span><span class="n">args</span><span class="o">.</span><span class="n">first</span><span class="o">.</span><span class="n">kind_of?</span><span class="p">(</span><span class="no">Hash</span><span class="p">))</span>
 <span class="n">proxy_found</span><span class="o">.</span><span class="n">first</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
 <span class="k">else</span>
 <span class="n">find</span><span class="p">(</span><span class="ss">:first</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">)</span>
 <span class="k">end</span>
 <span class="k">end</span>

 <span class="k">def</span> <span class="nf">last</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
 <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">first</span><span class="o">.</span><span class="n">kind_of?</span><span class="p">(</span><span class="nb">Integer</span><span class="p">)</span> <span class="o">||</span> <span class="p">(</span><span class="vi">@found</span> <span class="o">&&</span> <span class="o">!</span><span class="n">args</span><span class="o">.</span><span class="n">first</span><span class="o">.</span><span class="n">kind_of?</span><span class="p">(</span><span class="no">Hash</span><span class="p">))</span>
 <span class="n">proxy_found</span><span class="o">.</span><span class="n">last</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
 <span class="k">else</span>
 <span class="n">find</span><span class="p">(</span><span class="ss">:last</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">)</span>
 <span class="k">end</span>
 <span class="k">end</span>

 <span class="k">def</span> <span class="nf">size</span>
 <span class="vi">@found</span> <span class="p">?</span> <span class="vi">@found</span><span class="o">.</span><span class="n">length</span> <span class="p">:</span> <span class="n">count</span>
 <span class="k">end</span>

 <span class="k">def</span> <span class="nf">empty?</span>
 <span class="vi">@found</span> <span class="p">?</span> <span class="vi">@found</span><span class="o">.</span><span class="n">empty?</span> <span class="p">:</span> <span class="n">count</span><span class="o">.</span><span class="n">zero?</span>
 <span class="k">end</span>

 <span class="k">def</span> <span class="nf">respond_to?</span><span class="p">(</span><span class="nb">method</span><span class="p">,</span> <span class="n">include_private</span> <span class="o">=</span> <span class="kp">false</span><span class="p">)</span>
 <span class="k">super</span> <span class="o">||</span> <span class="vi">@proxy_scope</span><span class="o">.</span><span class="n">respond_to?</span><span class="p">(</span><span class="nb">method</span><span class="p">,</span> <span class="n">include_private</span><span class="p">)</span>
 <span class="k">end</span>

 <span class="k">def</span> <span class="nf">any?</span>
 <span class="k">if</span> <span class="nb">block_given?</span>
 <span class="n">proxy_found</span><span class="o">.</span><span class="n">any?</span> <span class="p">{</span> <span class="o">|*</span><span class="n">block_args</span><span class="o">|</span> <span class="k">yield</span><span class="p">(</span><span class="o">*</span><span class="n">block_args</span><span class="p">)</span> <span class="p">}</span>
 <span class="k">else</span>
 <span class="o">!</span><span class="n">empty?</span>
 <span class="k">end</span>
 <span class="k">end</span>

 <span class="c1"># Returns true if the named scope has more than 1 matching record.</span>
 <span class="k">def</span> <span class="nf">many?</span>
 <span class="k">if</span> <span class="nb">block_given?</span>
 <span class="n">proxy_found</span><span class="o">.</span><span class="n">many?</span> <span class="p">{</span> <span class="o">|*</span><span class="n">block_args</span><span class="o">|</span> <span class="k">yield</span><span class="p">(</span><span class="o">*</span><span class="n">block_args</span><span class="p">)</span> <span class="p">}</span>
 <span class="k">else</span>
 <span class="n">size</span> <span class="o">></span> <span class="mi">1</span>
 <span class="k">end</span>
 <span class="k">end</span>

 <span class="kp">protected</span>
 <span class="k">def</span> <span class="nf">proxy_found</span>
 <span class="vi">@found</span> <span class="o">||</span> <span class="n">load_found</span>
 <span class="k">end</span>

 <span class="kp">private</span>
 <span class="k">def</span> <span class="nf">method_missing</span><span class="p">(</span><span class="nb">method</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">&</span><span class="n">block</span><span class="p">)</span>
 <span class="k">if</span> <span class="n">scopes</span><span class="o">.</span><span class="n">include?</span><span class="p">(</span><span class="nb">method</span><span class="p">)</span>
 <span class="n">scopes</span><span class="o">[</span><span class="nb">method</span><span class="o">].</span><span class="n">call</span><span class="p">(</span><span class="nb">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">)</span>
 <span class="k">else</span>
 <span class="n">with_scope</span><span class="p">({</span><span class="ss">:find</span> <span class="o">=></span> <span class="n">proxy_options</span><span class="p">,</span> <span class="ss">:create</span> <span class="o">=></span> <span class="n">proxy_options</span><span class="o">[</span><span class="ss">:conditions</span><span class="o">].</span><span class="n">is_a?</span><span class="p">(</span><span class="no">Hash</span><span class="p">)</span> <span class="p">?</span> <span class="n">proxy_options</span><span class="o">[</span><span class="ss">:conditions</span><span class="o">]</span> <span class="p">:</span> <span class="p">{}},</span> <span class="ss">:reverse_merge</span><span class="p">)</span> <span class="k">do</span>
 <span class="nb">method</span> <span class="o">=</span> <span class="ss">:new</span> <span class="k">if</span> <span class="nb">method</span> <span class="o">==</span> <span class="ss">:build</span>
 <span class="k">if</span> <span class="n">current_scoped_methods_when_defined</span> <span class="o">&&</span> <span class="o">!</span><span class="n">scoped_methods</span><span class="o">.</span><span class="n">include?</span><span class="p">(</span><span class="n">current_scoped_methods_when_defined</span><span class="p">)</span>
 <span class="n">with_scope</span> <span class="n">current_scoped_methods_when_defined</span> <span class="k">do</span>
 <span class="n">proxy_scope</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="nb">method</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">&</span><span class="n">block</span><span class="p">)</span>
 <span class="k">end</span>
 <span class="k">else</span>
 <span class="n">proxy_scope</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="nb">method</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">&</span><span class="n">block</span><span class="p">)</span>
 <span class="k">end</span>
 <span class="k">end</span>
 <span class="k">end</span>
 <span class="k">end</span>

 <span class="k">def</span> <span class="nf">load_found</span>
 <span class="vi">@found</span> <span class="o">=</span> <span class="n">find</span><span class="p">(</span><span class="ss">:all</span><span class="p">)</span>
 <span class="k">end</span>
 <span class="k">end</span>
 <span class="k">end</span>
<span class="k">end</span>
</pre>
</div>
</div>
</div>
|
|
</div>
|
|
<div id="sidebar">
|
|
<h4>Twitter <a class="small" href="http://twitter.com/kennethreitz">@kennethreitz</a></h4>
|
|
<div id='twitter'>
|
|
<ul id='twitter_status'>
|
|
Status updating...
|
|
</ul>
|
|
</div>
|
|
<h4>My Delicious <a class="small" href="http://delicious.com/drummer42">more →</a></h4>
|
|
<div id='delicious'>
|
|
<script src='http://feeds.delicious.com/v2/js/drummer42?title=&count=3&sort=date&extended' type='text/javascript'></script>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id='footer'>
|
|
<div class='content'>
|
|
Copyright © 2010 - code.kennethreitz.com -
|
|
<span class='credit'>Powered by <a href="http://octopress.org">Octopress</a></span>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|