Skip to content

Commit

Permalink
Merge branch 'classer'
Browse files Browse the repository at this point in the history
  • Loading branch information
tal committed Jan 31, 2011
2 parents 2fb80b0 + 588d55c commit a81b390
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 1 deletion.
15 changes: 15 additions & 0 deletions README.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,21 @@ If you've initialized the Yajl, JSON, or Active Service gems you can call .json
url = URL.new('https://graph.facebook.com/37901410')
url.get.json # => => {"name"=>"Tal Atlas", "gender"=>"male", "id"=>"37901410", "last_name"=>"Atlas", "locale"=>"en_US", "link"=>"http://www.facebook.com/talatlas", "first_name"=>"Tal"}

=== Make Custom Objects

Make objects designed around specific urls

class FacebookURL < URL('http://www.facebook.com/__test_me__/foo/__test_again__')
allow_changed :subdomain
allow_params :foo, :bar
end

This will create a FacebookURL object where you can only change the subdomain, the params foo and bar, and the parts of the paths tagged
test_me and test_again. This object has the getters and setters: subdomain, foo, bar, test_me, and test_again. You can then call .to_s,
.get, .post, or .delete.

The object has an instance variable defined as @url which is a url object you can manipulate.

== TODO
* Fast Dup method
* More Documentation
Expand Down
3 changes: 2 additions & 1 deletion lib/url.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@


files = Dir.glob(File.join(File.dirname(__FILE__),'url','*.rb'))
files.delete_if {|f| f =~ /url\/(classer)\.rb/}
files.each { |f| require f }

# Main class for managing urls
Expand Down Expand Up @@ -190,7 +191,7 @@ def delete(*args)
end

def inspect
"#<URL #{to_s}>"
"#<#{self.class} #{to_s}>"
end

def dup
Expand Down
107 changes: 107 additions & 0 deletions lib/url/classer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
module URL::Classer
VAR_MATCHER = /__([A-Za-z]?[A-Za-z_]*[A-Za-z])__/

module ClassMethods
def allowed_params
@allowed_params ||= []
end
private
def allow_changed *args
args.flatten!
def_delegators :@url, :subdomains if args.include?(:subdomain)
def_delegators :@url, :subdomain if args.include?(:subdomains)
def_delegators :@url, :[], :[]= if args.include?(:params)
def_delegators :@url, *args
end

def allow_params *args
args.flatten.each do |arg|
arg = arg.to_sym
self.allowed_params << arg
define_method arg do
@url.params[arg]
end

define_method "#{arg}=" do |val|
@url.params[arg] = val
end
end
end

def overrideable_path_val v
v = v.to_s.downcase
define_method v do
@var_map[v]
end

define_method "#{v}=" do |val|
@var_map[v] = val

p = self.class.const_get(:URL).path.dup

@var_map.each do |key,value|
p.gsub!("__#{key}__", value.to_s)
end

@url.path = p

val
end
end

end

module InstanceMethods
def initialize(opts={})
@url = self.class.const_get(:URL).dup

@var_map = {}

opts.each do |op,v|
send("#{op}=",v)
end
end

def to_s
@url.to_s
end

def dup
n_url = @url.dup
n = super
n.instance_variable_set(:@url, n_url)
n
end

end

def self.included(receiver)
receiver.extend Forwardable
receiver.send :def_delegators, :@url, :get, :post, :delete, :inspect

receiver.extend ClassMethods
receiver.send :include, InstanceMethods
end
end

def URL url
if url.is_a?(URL)
url = url.dup
else
url = ::URL.new(url)
end

klass = Class.new do
include URL::Classer

vars = url.path.scan(URL::Classer::VAR_MATCHER).flatten

vars.each do |var|
overrideable_path_val(var)
end
end

klass.const_set(:URL, url.freeze)

klass
end
66 changes: 66 additions & 0 deletions spec/classer_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
require 'url/classer'

describe "URL()" do

before(:all) do
class FacebookURL < URL('http://www.facebook.com/__test_me__/foo/__test_again__')
allow_changed :subdomain
allow_params :foo, :bar
end
end

it "should create a class" do
url = 'http://www.facebook.com'
lambda {class FacebookURL2 < URL(url); end}.should_not raise_error

FacebookURL2.new.to_s.should == 'http://www.facebook.com/'
FacebookURL2.new.should be_a(URL::Classer)
end

context '.new' do
subject {FacebookURL.new}

it "shoud work like whatever" do
subject.subdomain << 'us'
subject.to_s.should =~ /^http:\/\/www\.us\.facebook.com/

u = FacebookURL.new
u.to_s.should =~ /^http:\/\/www\.facebook.com/
end

it "should dup" do
subject.subdomain << 'us'
d = subject.dup
d.subdomain.should == ['www','us']

d.subdomain << '1'
d.subdomain.should == ['www','us','1']
subject.subdomain.should == ['www','us']
end

it "should allow params" do
subject.foo = 1
subject.foo.should == 1
subject.to_s.should =~ /foo=1/
end

it "should set vars" do
subject.test_me = 'foobar'
subject.test_me.should == 'foobar'

subject.test_again = 'abc'
subject.to_s.should == "http://www.facebook.com/foobar/foo/abc"

subject.test_again = 'aaa'
subject.to_s.should == "http://www.facebook.com/foobar/foo/aaa"
end

it "should set vars in create" do
u = FacebookURL.new(:test_me => 'foobar', :test_again => 'abc')

u.to_s.should == "http://www.facebook.com/foobar/foo/abc"
end
end

end

0 comments on commit a81b390

Please sign in to comment.