forked from cldwalker/cldwalker.github.com
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
144 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
--- | ||
layout: post | ||
title: Tags, Trees and Facets, Oh My! | ||
--- | ||
|
||
I've recently "rekindled my affair with organizing tags":http://github.com/cldwalker/tag-tree/tree/master. As in the "past":http://search.cpan.org/%7Ebozo/Fry-Lib-CDBI-Basic-0.15/lib/Fry/Lib/CDBI/Outline.pm, I started by outlining my tags. But this time some of it seems to be making sense. | ||
|
||
Inspired by "wordnet":http://wordnetweb.princeton.edu/, I initially tried to organize my tags into lexical trees/outlines. This means I tried to organize the tags/words not by what they mean to me but what they mean to everybody. I gave up on this as my tags began to differ to much from what the word actually meant. (Yes, I'll have to revisit this someday when I want to effectively share my tag relationships with others.) | ||
|
||
So I began organizing my tags semantically ie what they mean to me. Trying to learn from past pitfalls, I resisted the urge to make mega tag trees and instead made multiple, lean inheritance trees. For an example of an inheritance tree, take this one of my learning_subject tag: | ||
<pre> | ||
learning_subject | ||
math | ||
science | ||
chem | ||
bio | ||
astro | ||
physics | ||
philosophy | ||
art | ||
</pre> | ||
|
||
Reading from a leaf node to the root: chem (chemistry) is a science is a learning_subject. Of what use is this inheritance tree? Smarter querying and less tag pollution. If I tag an item with physics, I can alternatively get it back using my science or learning_subject tag. Less tag pollution because I don't have to tag every physics item with science and learning_subject as well. (Nothing new for you "semantic":http://zigtag.com/ "taggers":http://faviki.com/ "out there":http://entitydescriber.org/). | ||
|
||
The more I organized my tags, the more I noticed that most of my trees were just lists. Why so many lists? I had tag lists of colors, programming languages, music genres, applications ... Were these nascent inheritance trees or "facets":http://en.wikipedia.org/wiki/Faceted_classification ? Were they serving as attributes of objects? The more I looked around at my tags, the more I saw that I had been forming different objects with tags. I had application objects that had attributes of a programming language, app type, operating system, etc. I had blog post objects that had attributes of learning type, programming language, author, etc. __In not treating tags as attribute values of a tag object, I had been cluttering my tags and losing semantic goodness.__ I had no idea if my tags were referring to an application mentioned in the webpage or the webpage itself. (Food for thought: at what point do facets become complex enough to be treated as an inheritance tree? What's the significance of that?) | ||
|
||
So it looks like it's time for OO-tagging. With OO-tagging will come defining relationships between tag objects. I've also been itching to add modifiers between tags and their tagged subjects (either with a preposition or verb). Perhaps I can kill object relationships and modifiers with one coding stone. Then again, maybe "W is respected abroad":http://uk.youtube.com/watch?v=OM3Z_Kskl_U . |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
--- | ||
layout: post | ||
title: Block to Hash Conversion for Ruby Config Blocks | ||
--- | ||
|
||
While I was busy scratching "an irb itch":http://github.com/cldwalker/alias, I came up with a handy technique for converting a method's block definition into a hash. Here's an example of using such a method: | ||
|
||
{% highlight ruby %} | ||
Alias.init do |a| | ||
a.verbose = true | ||
a.constant = {'Array' = 'A'} | ||
a.instance_method = {'String'=>{'downcase'=>'dc' },'Array'=>{'select'=>'s'}} | ||
end | ||
{% endhighlight %} | ||
|
||
What I wanted was a quick but _clean_ way to convert the data structure described in the method's block to a hash. So knowing about OpenStruct, I peered into its internals and saw that it stores its attributes as a hash in <notextile>@table. Since there isn't a public method for @table, I realized I was going to have to use instance_variable_get(:@table)</notextile>. Now if I only wanted to be quick, I could simply have used that. But wanting code clarity (ie not have to read OpenStruct's internal variables each time) and to avoid monkeypatching (I have been bitten), I came up with: | ||
|
||
<script src="http://gist.github.com/50171.js"></script> | ||
|
||
Using it is simple. Pass your method's block to ConfigStruct.block_to_hash() and you'll get back a hash with whatever was defined in the block: | ||
|
||
{% highlight ruby %} | ||
def init(*args, &block) | ||
config = ConfigStruct.block_to_hash(block) | ||
#process your config ... | ||
end | ||
|
||
init do |c| | ||
c.some = "config" | ||
c.info = "goes here" | ||
end | ||
# In init(), config = {:some=>'config', :info=>'goes here'} | ||
{% endhighlight %} | ||
|
||
If you decide to not pass your method a block? No worries. You get back an empty hash. To see this idea in my ruby gem, see "here":http://github.com/cldwalker/alias/blob/master/lib/alias.rb. |
63 changes: 63 additions & 0 deletions
63
_posts/2009-01-31-share-extensions-without-monkey-patching.textile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
--- | ||
layout: post | ||
title: Can We Share Our Extensions Without Monkey Patching? | ||
--- | ||
|
||
As Ruby programmers, I think we enjoy the ease and power of being able to extend any core Ruby class. As our ruby-fu grows, we pick up some tricks to have Hash's and Struct's to do our bidding, monkeypatched or not. So naturally we start collecting extensions. Sometimes they're cool enough to blog about, sometimes you find out a week later that "Ruby's stdlib":http://www.ruby-doc.org/stdlib/ or "activesupport":http://as.rubyonrails.com/ already does it better. Eventually collecting enough of them, you decide to "gem":http://rubyforge.org/ or "github":http://github.com them because you want to share what you've learned. You want others to use it. Heck, maybe even get feedback on them. So when releasing them, why do we force monkeypatching? | ||
|
||
{% highlight ruby %} | ||
|
||
class Object | ||
def awesome_instance_method | ||
end | ||
def self.awesomer_class_method | ||
end | ||
end | ||
{% endhighlight %} | ||
|
||
Why do this when it's easy to do the same without monkeypatching? | ||
|
||
{% highlight ruby %} | ||
module Awesome | ||
module Object | ||
def awesome_instance_method | ||
end | ||
|
||
module ClassMethods | ||
def awesomer_class_method | ||
end | ||
end | ||
end | ||
end | ||
|
||
# In a separate file that you will require: | ||
Object.send :include, Awesome::Object | ||
Object.send :extend, Awesome::Object::ClassMethods | ||
{% endhighlight %} | ||
|
||
No, I'm not trying to reignite "monkeypatch debates":http://www.ruby-forum.com/topic/143732. Rather, just hoping that as a community, we can release monkeypatch-agnostic extensions and let the programmer decide when to monkeypatch. | ||
|
||
So why do I think everybody monkeypatches their extensions? Take a look at some of the Ruby extension libraries out there: | ||
* "activesupport":http://as.rubyonrails.com | ||
* "facets":http://facets.rubyforge.org/ | ||
* "extlib":http://github.com/sam/extlib/tree/master | ||
* "merb-extlib":http://github.com/wycats/merb-extlib/tree/master | ||
* "extensions":http://extensions.rubyforge.org/rdoc/index.html | ||
* "awesomeness":http://github.com/collectiveidea/awesomeness/tree/master | ||
* "hubahuba":http://github.com/github/hubahuba/tree/master | ||
* "quality_extensions":http://github.com/TylerRick/quality_extensions/tree/master | ||
* "ruby-nuggets":http://github.com/blackwinter/ruby-nuggets/tree/master | ||
* "my.rb":http://github.com/elliottcable/my.rb/tree/master | ||
* "mini_facet":http://github.com/webmat/mini_facet/tree/master | ||
|
||
And there's still more on "github":http://github.com/search?type=Repositories&language=rb&q=description%3A%28%2Bruby+%2Bextensions%29&repo=&langOverride=&x=0&y=0&start_value=1 ... | ||
Of the above extensions, ActiveSupport is the **ONLY** one that doesn't force monkeypatching: | ||
|
||
{% highlight ruby %} | ||
gem 'activesupport' | ||
require 'active_support/core_ext/array/access' | ||
class My; class Array < ::Array; end; end | ||
My::Array.send :include, ActiveSupport::CoreExtensions::Array::Access | ||
{% endhighlight %} | ||
|
||
So can we share our extensions without monkeypatching? |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters