Permalink
Browse files

First three posts and massive style improvements!

  • Loading branch information...
1 parent b23e69b commit 6ef581a0374cea1d7448d09c9e4c545cfe2fe4ad @jqr committed Feb 1, 2009
View
@@ -0,0 +1,2 @@
+.DS_Store
+_site/
View
0 README
No changes.
View
@@ -0,0 +1,88 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en-us">
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+ <title>
+ {% if page.title %}
+ {{ page.title }} //
+ {% endif %}
+ Elijah Miller
+ </title>
+ <meta name="author" content="Elijah Miller" />
+ <link href="http://feeds.feedburner.com/jqr" rel="alternate" title="Elijah Miller" type="application/atom+xml" />
+
+ <link rel="stylesheet" href="/stylesheets/syntax.css" type="text/css" />
+ <link rel="stylesheet" href="/stylesheets/default.css" type="text/css" media="screen, projection" />
+ </head>
+ <body>
+ <a href="http://github.com/jqr"><img style="position: absolute; top: 0; left: 0; border: 0;" src="http://s3.amazonaws.com/github/ribbons/forkme_left_orange_ff7600.png" alt="Fork me on GitHub" /></a>
+
+ <div id="site">
+ <a id="subscribe" href="http://feeds.feedburner.com/jqr"><img src="/images/rss.png" alt="Subscribe to RSS Feed" /></a>
+
+ <h1><a href="/">Elijah Miller</a></h1>
+
+ <div class="clear"></div>
+
+ <div id="sidebar">
+ <h3>Me</h3>
+ <dl id="contact">
+ <dt>Name</dt>
+ <dd>Elijah Miller / jqr</dd>
+
+ <dt>Email</dt>
+ <dd><a href="mailto:elijah.miller@gmail.com">elijah.miller@gmail.com</a></dd>
+
+ </dl>
+ <h3>And then some</h3>
+ <ul id="profiles">
+ <li><a href="http://twitter.com/jqr">Twitter</a></li>
+
+ <li><a href="http://github.com/jqr">GitHub</a></li>
+
+ <li><a href="http://workingwithrails.com/person/6150-elijah-miller">WorkingWithRails</a></li>
+
+ <li><a href="http://www.linkedin.com/in/elijahmiller">LinkedIn</a></li>
+ </ul>
+
+ <a href="http://www.workingwithrails.com/recommendation/new/person/6150-elijah-miller"><img src="http://workingwithrails.com/images/tools/compact-small.jpg" alt="Recommend me at Working With Rails"></a>
+ </div>
+
+ <div id="content">
+ {{ content }}
+ </div>
+
+ <div class="clear"></div>
+
+ </div>
+
+ <script type="text/javascript">
+ //<![CDATA[
+ (function() {
+ var links = document.getElementsByTagName('a');
+ var query = '?';
+ for(var i = 0; i < links.length; i++) {
+ if(links[i].href.indexOf('#disqus_thread') >= 0) {
+ query += 'url' + i + '=' + encodeURIComponent(links[i].href) + '&';
+ }
+ }
+ document.write('<script type="text/javascript" src="http://disqus.com/forums/jqr/get_num_replies.js' + query + '"></' + 'script>');
+ })();
+ //]]>
+ </script>
+
+ <script type="text/javascript">
+ var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+ document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+ </script>
+ <script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-254246-10");
+ pageTracker._trackPageview();
+ } catch(err) {}
+ </script>
+
+ </body>
+</html>
View
@@ -0,0 +1,21 @@
+---
+layout: default
+---
+
+<div id="post">
+ <h2>{{ page.title }}</h2>
+ {{ content }}
+</div>
+
+<div id="disqus_thread"></div><script type="text/javascript" src="http://disqus.com/forums/jqr/embed.js"></script><noscript><a href="http://jqr.disqus.com/?url=ref">View comments.</a></noscript>
+
+<!--
+ <div id="related">
+ <h2>Related Posts</h2>
+ <ul class="posts">
+ {% for post in site.related_posts limit:3 %}
+ <li><span>{{ post.date | date_to_string }}</span> &raquo; <a href="{{ post.url }}">{{ post.title }}</a></li>
+ {% endfor %}
+ </ul>
+ </div>
+-->
@@ -0,0 +1,14 @@
+---
+layout: post
+title: All My Code Are Belong to Us
+---
+
+I've really been pushing myself to move as much code as possible into the public space. <a href="http://github.com">GitHub</a> has come at a perfect time to encourage this behavior. It makes the tedious process of sharing code so easy you'd be stupid not to.
+
+I put all of it <a href="http://github.com/jqr">directly on GitHub</a> as a Rails plugin and a Ruby gem. Learning how to do this is a few hours of investment, but it's an investment you only need to make once. I'm using <a href="http://blog.evanweaver.com/files/doc/fauna/echoe/files/README.html">Echoe</a> right now, but I'll probably switch to <a href="http://technicalpickles.com/posts/craft-the-perfect-gem-with-jeweler">Jeweler</a> for even simpler releases.
+
+I am certain that making code reusable is one of the best ways to gain a solid understanding of how a software developer's tools should be used. Polishing up code for public release encourages a ton of good behavior that makes even personal reuse easier and as a side benefit, other people will improve my code for free!
+
+Most of the plugins and gems I write are simple enhancements to patterns and are the result of DRYing up code in a single project. After abstracting the initial idea from one project, I find it's much easier to recognize the same pattern in other projects.
+
+So take a few minutes and look for patterns in your code. Give the pattern a name. Uncover the simplest way to express it. Start using it. Discover it's limitations. Publish it. Talk about it.
@@ -0,0 +1,68 @@
+---
+layout: post
+title: Making Rails' Serialize Even Better
+---
+
+Rails has this handy method that allows you store almost any object in the database with ease. Most often I end up using it for storing optional attributes in a hash.
+
+Here is the proper syntax for telling Rails that there is an options attribute that should only store Hash values.
+
+{% highlight ruby %}
+class User < ActiveRecord::Base
+ serialize :options, Hash
+end
+{% endhighlight %}
+
+<h3>The problem</h3>
+
+The options attribute will start off as nil, and remain nil until you set it to something else. Setting the class_name to Hash only affects what you can write to this attribute.
+
+{% highlight irb %}
+>> user = User.new
+=> #<User id: nil, name: nil, options: nil>
+>> user.options[:theme]
+NoMethodError: You have a nil object when you didn't expect it!
+You might have expected an instance of ActiveRecord::Base.
+The error occurred while evaluating nil.[]
+ from (irb):2
+=> nil
+{% endhighlight %}
+
+<h3>The solution</h3>
+What we really need is to automatically return an empty Hash on this new object so we can go on our merry way.
+
+Add this to your environment.rb.
+
+{% highlight ruby %}
+config.gem 'jqr-typed_serialize',
+ :lib => 'typed_serialize',
+ :source => 'http://gems.github.com'
+{% endhighlight %}
+
+Now run this command to install the gem.
+{% highlight sh %}
+$ rake gems:install
+{% endhighlight %}
+
+A quick change of our model will fix all of our woes.
+{% highlight ruby %}
+class User < ActiveRecord::Base
+ typed_serialize :options, Hash
+end
+{% endhighlight %}
+
+{% highlight irb %}
+>> user = User.new
+=> #<User id: nil, name: nil, options: nil>
+>> user.options[:theme]
+=> nil
+>> user.options
+=> {}
+{% endhighlight %}
+
+Voila!
+
+<h3>The how and why</h3>
+
+If you're curious about how this works, I've written a simple post describing the <a href="/2009/02/01/the-making-of-typed-serialize.html">the making of typed_serialize</a>, or you can <a href="http://github.com/jqr/typed_serialize">browse the code</a>.
+
@@ -0,0 +1,122 @@
+---
+layout: post
+title: The Making of typed_serialize
+---
+
+My <a href="http://github.com/jqr/typed_serialize">typed_serialize plugin</a> came from the repetition of code just like this.
+
+{% highlight ruby %}
+def options
+ value = super
+ if value.is_a?(Hash)
+ value
+ else
+ self.options = {}
+ end
+end
+{% endhighlight %}
+
+It calls super to peek at what ActiveRecord would return for the serialized column. If it's a Hash, we just return it right away. If it's anything else we set it to a new Hash and return that.
+
+
+<h3>Distilling the interface</h3>
+
+After thinking about the pattern for a bit, I decided that simplest shorthand would be this.
+
+{% highlight ruby %}
+class User < ActiveRecord::Base
+ typed_serialize :options, Hash
+end
+{% endhighlight %}
+
+This code says "there is a typed and serialized attribute named options, that will always be a Hash." Notice that it is nearly the same usage as the original serialize method.
+
+
+<h3>Get to it</h3>
+
+First off, we define a method that is accessible at the time of class definition. Since the usage is the same as serialize, we can use the original serialize method definition as a starting point.
+
+{% highlight ruby %}
+class ActiveRecord::Base
+ def self.typed_serialize(attr_name, class_name = Object)
+ end
+end
+{% endhighlight %}
+
+On second thought, what's the point of class_name being optional? It made sense for the original serialize method, but not typed_serialize. Let's make class_name mandatory.
+
+{% highlight ruby %}
+class ActiveRecord::Base
+ def self.typed_serialize(attr_name, class_name)
+ end
+end
+{% endhighlight %}
+
+
+OK, now our User model can properly execute, but it does absolutely nothing. So let's at least call Rails' serialize method to get the standard behavior.
+
+{% highlight ruby %}
+class ActiveRecord::Base
+ def self.typed_serialize(attr_name, class_name = Object)
+ serialize(attr_name, class_name)
+ end
+end
+{% endhighlight %}
+
+<h3>Adding the meat</h3>
+
+Our repeated code revolved around a custom reader for a serialized attribute. So let's add a custom reader for attr_name using define_method and our original repeated code.
+
+{% highlight ruby %}
+class ActiveRecord::Base
+ def self.typed_serialize(attr_name, class_name = Object)
+ serialize(attr_name, class_name)
+
+ define_method(attr_name) do
+ value = super
+ if value.is_a?(Hash)
+ value
+ else
+ self.options = {}
+ end
+ end
+ end
+end
+{% endhighlight %}
+
+The original code has a couple of small problems. It assumes the value should always be a Hash and written attribute is always named options.
+
+A quick look at serialize's implementation tells us it stores its data a hash with the key as the attribute name in string form, and the value is the class_name.
+
+{% highlight ruby %}
+expected_class = self.class.serialized_attributes[attr_name.to_s]
+{% endhighlight %}
+
+We'll use Ruby's send method to call a method with a name we won't know until runtime.
+
+{% highlight ruby %}
+send("#{attr_name}=", expected_class.new)
+{% endhighlight %}
+
+<h3>All together now.</h3>
+
+{% highlight ruby %}
+class ActiveRecord::Base
+ def self.typed_serialize(attr_name, class_name = Object)
+ serialize(attr_name, class_name)
+
+ define_method(attr_name) do
+ expected_class = self.class.serialized_attributes[attr_name.to_s]
+
+ value = super
+ if value.is_a?(expected_class)
+ value
+ else
+ send("#{attr_name}=", expected_class.new)
+ end
+ end
+ end
+end
+{% endhighlight %}
+
+This is my first post detailing an implementation. Interestingly enough, it alerted me to a few unnecessarily complex portions of even this tiny amount of code.
View
@@ -0,0 +1,27 @@
+---
+layout: nil
+---
+<?xml version="1.0" encoding="utf-8"?>
+<feed xmlns="http://www.w3.org/2005/Atom">
+
+ <title>Elijah Miller</title>
+ <link href="http://test.com/atom.xml" rel="self"/>
+ <link href="http://test.com/"/>
+ <updated>{{ site.time | date_to_xmlschema }}</updated>
+ <id>http://test.com/</id>
+ <author>
+ <name>Elijah hMiller</name>
+ <email>elijah.miller@gmail.com</email>
+ </author>
+
+ {% for post in site.posts %}
+ <entry>
+ <title>{{ post.title }}</title>
+ <link href="http://test.com{{ post.url }}"/>
+ <updated>{{ post.date | date_to_xmlschema }}</updated>
+ <id>http://test.com{{ post.id }}</id>
+ <content type="html">{{ post.content | xml_escape }}</content>
+ </entry>
+ {% endfor %}
+
+</feed>
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
@@ -1 +1,29 @@
-testing
+---
+layout: default
+---
+
+<div id="home">
+ <h2>Posts</h2>
+ <ul class="posts">
+ {% for post in site.posts %}
+ <li><span>{{ post.date | date_to_string }}</span>: <a href="{{ post.url }}">{{ post.title }}</a></li>
+ {% endfor %}
+ </ul>
+
+ <h2>Tweets</h2>
+ <div id="tweets">
+ Loading...
+ </ul>
+
+ <script type="text/javascript" src="/javascripts/twitter-1.11.2.js"></script>
+
+ <script type="text/javascript">
+ getTwitters('tweets', {
+ id: 'jqr',
+ count: 5,
+ enableLinks: true,
+ clearContents: true,
+ template: '%text%'
+ });
+ </script>
+</div>
Oops, something went wrong.

0 comments on commit 6ef581a

Please sign in to comment.