smg 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +6 -62
 - data/examples/discogs/label.rb +62 -0
 - data/examples/discogs/search.rb +60 -0
 - data/examples/plant.rb +1 -2
 - data/examples/twitter.rb +8 -5
 - data/examples/weather.rb +146 -0
 - data/lib/smg.rb +4 -0
 - data/lib/smg/document.rb +25 -8
 - data/lib/smg/http.rb +66 -0
 - data/lib/smg/http/exceptions.rb +37 -0
 - data/lib/smg/http/request.rb +126 -0
 - data/lib/smg/mapping.rb +11 -1
 - data/lib/smg/mapping/element.rb +29 -13
 - data/lib/smg/mapping/typecasts.rb +2 -1
 - data/lib/smg/model.rb +9 -3
 - data/lib/smg/resource.rb +5 -1
 - data/spec/collect_spec.rb +254 -0
 - data/spec/context_spec.rb +189 -0
 - data/spec/extract_spec.rb +200 -0
 - data/spec/filtering_spec.rb +164 -0
 - data/spec/fixtures/discogs/948224.xml +1 -0
 - data/spec/fixtures/discogs/Enzyme+Records.xml +9 -0
 - data/spec/fixtures/discogs/Genosha+Recordings.xml +13 -0
 - data/spec/fixtures/discogs/Ophidian.xml +6 -0
 - data/spec/fixtures/fake/malus.xml +18 -0
 - data/spec/fixtures/fake/valve.xml +8 -0
 - data/spec/fixtures/twitter/pipopolam.xml +46 -0
 - data/spec/fixtures/yahoo.weather.com.xml +50 -0
 - data/spec/http/request_spec.rb +186 -0
 - data/spec/http/shared/automatic.rb +43 -0
 - data/spec/http/shared/non_automatic.rb +36 -0
 - data/spec/http/shared/redirectable.rb +30 -0
 - data/spec/http_spec.rb +76 -0
 - data/spec/lib/helpers/http_helpers.rb +27 -0
 - data/spec/lib/matchers/instance_methods.rb +38 -0
 - data/spec/mapping/element_spec.rb +241 -0
 - data/spec/mapping/typecasts_spec.rb +52 -0
 - data/spec/resource_spec.rb +30 -0
 - data/spec/root_spec.rb +26 -0
 - data/spec/spec_helper.rb +23 -0
 - metadata +53 -10
 - data/examples/discogs.rb +0 -39
 
    
        data/spec/http_spec.rb
    ADDED
    
    | 
         @@ -0,0 +1,76 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.expand_path File.join(File.dirname(__FILE__), 'spec_helper')
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe SMG::HTTP::Model, ".uri_for" do
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              before :all do
         
     | 
| 
      
 6 
     | 
    
         
            +
                @klass = Class.new { include SMG::Resource, SMG::HTTP }
         
     | 
| 
      
 7 
     | 
    
         
            +
                @klass.site "http://www.example.org"
         
     | 
| 
      
 8 
     | 
    
         
            +
                @klass.params "developer" => "Valve"
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              it "appends a path to the base URI" do
         
     | 
| 
      
 12 
     | 
    
         
            +
                uri = @klass.send(:uri_for, "search")
         
     | 
| 
      
 13 
     | 
    
         
            +
                uri.host.should == "www.example.org"
         
     | 
| 
      
 14 
     | 
    
         
            +
                uri.path.should == "/search"
         
     | 
| 
      
 15 
     | 
    
         
            +
                uri.query_values.should == {"developer" => "Valve"}
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              it "appends a query to the base URI" do
         
     | 
| 
      
 19 
     | 
    
         
            +
                uri = @klass.send(:uri_for, "search", {"cake" => "Lie"})
         
     | 
| 
      
 20 
     | 
    
         
            +
                uri.host.should == "www.example.org"
         
     | 
| 
      
 21 
     | 
    
         
            +
                uri.path.should == "/search"
         
     | 
| 
      
 22 
     | 
    
         
            +
                uri.query_values.should == {"developer" => "Valve", "cake" => "Lie"}
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            describe SMG::HTTP::Model do
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              before :all do
         
     | 
| 
      
 30 
     | 
    
         
            +
                @klass = Class.new { include SMG::Resource, SMG::HTTP }
         
     | 
| 
      
 31 
     | 
    
         
            +
                @klass.site "http://www.example.org"
         
     | 
| 
      
 32 
     | 
    
         
            +
                @klass.params "developer" => "Valve"
         
     | 
| 
      
 33 
     | 
    
         
            +
                @klass.extract "game/name"
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              Hash[[:get, :post, :put, :delete, :head].zip(SMG::HTTP::Request::VERBS)].each do |sym,verb|
         
     | 
| 
      
 37 
     | 
    
         
            +
                describe ".#{sym}" do
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  before :each do
         
     | 
| 
      
 40 
     | 
    
         
            +
                    @response = Net::HTTPOK.new('1.1', 200, "OK")
         
     | 
| 
      
 41 
     | 
    
         
            +
                    @response.stub!(:body).and_return("<game><name>Portal</name></game>")
         
     | 
| 
      
 42 
     | 
    
         
            +
                  end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                  before :each do
         
     | 
| 
      
 45 
     | 
    
         
            +
                    @request = mock('request')
         
     | 
| 
      
 46 
     | 
    
         
            +
                    @request.stub!(:perform).and_return(@response)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  before :each do
         
     | 
| 
      
 50 
     | 
    
         
            +
                    @headers = {"Accept-Encoding" => "gzip,deflate;*;q=0"}
         
     | 
| 
      
 51 
     | 
    
         
            +
                    @options = {:query => {"cake" => "LIE"}, :headers => @headers}
         
     | 
| 
      
 52 
     | 
    
         
            +
                    SMG::HTTP::Request.should_receive(:new).
         
     | 
| 
      
 53 
     | 
    
         
            +
                    with(verb, instance_of(Addressable::URI), {:headers => @headers}).
         
     | 
| 
      
 54 
     | 
    
         
            +
                    and_return(@request)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                  it "performs #{sym.to_s.upcase} request" do
         
     | 
| 
      
 58 
     | 
    
         
            +
                    @klass.send(sym, "game", @options)
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                  it "parses response' body when no block given" do
         
     | 
| 
      
 62 
     | 
    
         
            +
                    @game = @klass.send(sym, "game", @options)
         
     | 
| 
      
 63 
     | 
    
         
            +
                    @game.name.should == "Portal"
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                  it "yields response and parses the block returning value when block given" do
         
     | 
| 
      
 67 
     | 
    
         
            +
                    @game = @klass.send(sym, "game", @options) { |response| "<game><name>Portal2</name></game>" }
         
     | 
| 
      
 68 
     | 
    
         
            +
                    @game.name.should == "Portal2"
         
     | 
| 
      
 69 
     | 
    
         
            +
                  end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
              end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
            end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
            # EOF
         
     | 
| 
         @@ -0,0 +1,27 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Spec #:nodoc:
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Helpers #:nodoc:
         
     | 
| 
      
 3 
     | 
    
         
            +
                module HTTPHelpers
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  def http(uri, proxy = nil)
         
     | 
| 
      
 6 
     | 
    
         
            +
                    @http ||= mock('http')
         
     | 
| 
      
 7 
     | 
    
         
            +
                    uri = Addressable::URI.parse(uri)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    args = (proxy && p = Addressable::URI.parse(proxy)) ?
         
     | 
| 
      
 9 
     | 
    
         
            +
                      [uri.host, uri.port, p.host, p.port, p.user, p.password] :
         
     | 
| 
      
 10 
     | 
    
         
            +
                      [uri.host, uri.port]
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                    Net::HTTP.should_receive(:new).with(*args).and_return(@http)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def stub_response(code, message, *args)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    response = Net::HTTPResponse::CODE_TO_OBJ[code.to_s].new('1.1', code, message)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    response.initialize_http_header(Hash === args.last ? args.pop : {})
         
     | 
| 
      
 18 
     | 
    
         
            +
                    response.stub!(:body).and_return(args.join) unless args.empty?
         
     | 
| 
      
 19 
     | 
    
         
            +
                    @http.should_receive(:request).and_return response
         
     | 
| 
      
 20 
     | 
    
         
            +
                    response
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            # EOF
         
     | 
| 
         @@ -0,0 +1,38 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Spec #:nodoc:
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Matchers #:nodoc:
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                #http://github.com/rubyspec/mspec/blob/master/lib/mspec/matchers/have_instance_method.rb
         
     | 
| 
      
 5 
     | 
    
         
            +
                class HaveInstanceMethodMatcher
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  def initialize(method, include_super)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @method = method.to_sym
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @include_super = include_super
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def matches?(mod)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @mod = mod
         
     | 
| 
      
 14 
     | 
    
         
            +
                    mod.instance_methods(@include_super).include?(@method) || 
         
     | 
| 
      
 15 
     | 
    
         
            +
                    mod.instance_methods(@include_super).include?(@method.to_s)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  def failure_message
         
     | 
| 
      
 19 
     | 
    
         
            +
                    ["Expected #{@mod} to have instance method '#{@method.to_s}'",
         
     | 
| 
      
 20 
     | 
    
         
            +
                     "but it does not"]
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  def negative_failure_message
         
     | 
| 
      
 24 
     | 
    
         
            +
                    ["Expected #{@mod} NOT to have instance method '#{@method.to_s}'",
         
     | 
| 
      
 25 
     | 
    
         
            +
                     "but it does"]
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                module HaveInstanceMethodMixin
         
     | 
| 
      
 30 
     | 
    
         
            +
                  def have_instance_method(method, include_super=true)
         
     | 
| 
      
 31 
     | 
    
         
            +
                    HaveInstanceMethodMatcher.new method, include_super
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              end
         
     | 
| 
      
 36 
     | 
    
         
            +
            end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            # EOF
         
     | 
| 
         @@ -0,0 +1,241 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.expand_path File.join(File.dirname(__FILE__), '..', 'spec_helper')
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe SMG::Mapping::Element do
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              describe "#initialize" do
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                it "respects path" do
         
     | 
| 
      
 8 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','subnode'])
         
     | 
| 
      
 9 
     | 
    
         
            +
                  e.name.should == :subnode
         
     | 
| 
      
 10 
     | 
    
         
            +
                  e.accessor.should == :subnode=
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','ns:subnode'])
         
     | 
| 
      
 13 
     | 
    
         
            +
                  e.name.should == :ns_subnode
         
     | 
| 
      
 14 
     | 
    
         
            +
                  e.accessor.should == :ns_subnode=
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','subnode'], :nested => true)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  e.name.should == :subnode
         
     | 
| 
      
 18 
     | 
    
         
            +
                  e.accessor.should == :subnode=
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','ns:subnode'], :nested => true)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  e.name.should == :ns_subnode
         
     | 
| 
      
 22 
     | 
    
         
            +
                  e.accessor.should == :ns_subnode=
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                it "respects namespaces" do
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                it "respects :at option" do
         
     | 
| 
      
 29 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','subnode'], :at => :something)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  e.name.should == :something
         
     | 
| 
      
 31 
     | 
    
         
            +
                  e.accessor.should == :something=
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','ns:subnode'], :at => :something)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  e.name.should == :something
         
     | 
| 
      
 35 
     | 
    
         
            +
                  e.accessor.should == :something=
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','subnode'], :at => :something, :nested => true)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  e.name.should == :something
         
     | 
| 
      
 39 
     | 
    
         
            +
                  e.accessor.should == :something=
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','ns:subnode'], :at => :something, :nested => true)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  e.name.should == :something
         
     | 
| 
      
 43 
     | 
    
         
            +
                  e.accessor.should == :something=
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                it "respects :as option" do
         
     | 
| 
      
 47 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','subnode'], :at => :whatever, :as => :something)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  e.name.should == :something
         
     | 
| 
      
 49 
     | 
    
         
            +
                  e.accessor.should == :something=
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','ns:subnode'], :at => :whatever, :as => :something)
         
     | 
| 
      
 52 
     | 
    
         
            +
                  e.name.should == :something
         
     | 
| 
      
 53 
     | 
    
         
            +
                  e.accessor.should == :something=
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','subnode'], :as => :whatever, :nested => true)
         
     | 
| 
      
 56 
     | 
    
         
            +
                  e.name.should == :whatever
         
     | 
| 
      
 57 
     | 
    
         
            +
                  e.accessor.should == :whatever=
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','ns:subnode'], :as => :whatever, :nested => true)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  e.name.should == :whatever
         
     | 
| 
      
 61 
     | 
    
         
            +
                  e.accessor.should == :whatever=
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                it "respects :collection option" do
         
     | 
| 
      
 65 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','subnodes'], :collection => true)
         
     | 
| 
      
 66 
     | 
    
         
            +
                  e.name.should == :subnodes
         
     | 
| 
      
 67 
     | 
    
         
            +
                  e.accessor.should == :append_to_subnodes
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','ns:subnodes'], :collection => true)
         
     | 
| 
      
 70 
     | 
    
         
            +
                  e.name.should == :ns_subnodes
         
     | 
| 
      
 71 
     | 
    
         
            +
                  e.accessor.should == :append_to_ns_subnodes
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','subnodes'], :at => :something, :collection => true)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  e.name.should == :something
         
     | 
| 
      
 75 
     | 
    
         
            +
                  e.accessor.should == :append_to_something
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','ns:subnodes'], :at => :something, :collection => true)
         
     | 
| 
      
 78 
     | 
    
         
            +
                  e.name.should == :something
         
     | 
| 
      
 79 
     | 
    
         
            +
                  e.accessor.should == :append_to_something
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','subnodes'], :at => :whatever, :as => :something, :collection => true)
         
     | 
| 
      
 82 
     | 
    
         
            +
                  e.name.should == :something
         
     | 
| 
      
 83 
     | 
    
         
            +
                  e.accessor.should == :append_to_something
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','ns:subnodes'], :at => :whatever, :as => :something, :collection => true)
         
     | 
| 
      
 86 
     | 
    
         
            +
                  e.name.should == :something
         
     | 
| 
      
 87 
     | 
    
         
            +
                  e.accessor.should == :append_to_something
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','subnodes'], :as => :something, :collection => true)
         
     | 
| 
      
 90 
     | 
    
         
            +
                  e.name.should == :something
         
     | 
| 
      
 91 
     | 
    
         
            +
                  e.accessor.should == :append_to_something
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','ns:subnodes'], :as => :something, :collection => true)
         
     | 
| 
      
 94 
     | 
    
         
            +
                  e.name.should == :something
         
     | 
| 
      
 95 
     | 
    
         
            +
                  e.accessor.should == :append_to_something
         
     | 
| 
      
 96 
     | 
    
         
            +
                end
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                it "defaults @context to nil" do
         
     | 
| 
      
 99 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','subnode'])
         
     | 
| 
      
 100 
     | 
    
         
            +
                  e.context.should be_nil
         
     | 
| 
      
 101 
     | 
    
         
            +
                end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                describe "with :class option" do
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                  it "defines the @data_class if :class is an SMG::Model" do
         
     | 
| 
      
 106 
     | 
    
         
            +
                    klass = Class.new { include SMG::Resource }
         
     | 
| 
      
 107 
     | 
    
         
            +
                    e = SMG::Mapping::Element.new(['node'], :class => klass)
         
     | 
| 
      
 108 
     | 
    
         
            +
                    e.data_class.should == klass
         
     | 
| 
      
 109 
     | 
    
         
            +
                  end
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                  it "defines the @cast_to if :class is a valid typecast" do
         
     | 
| 
      
 112 
     | 
    
         
            +
                    klass = Class.new { include SMG::Resource }
         
     | 
| 
      
 113 
     | 
    
         
            +
                    e = SMG::Mapping::Element.new(['node'], :class => :string)
         
     | 
| 
      
 114 
     | 
    
         
            +
                    e.cast_to.should == :string
         
     | 
| 
      
 115 
     | 
    
         
            +
                  end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                  it "raises an ArgumentError otherwise" do
         
     | 
| 
      
 118 
     | 
    
         
            +
                    lambda { SMG::Mapping::Element.new(['node'], :class => "bogus!")}.
         
     | 
| 
      
 119 
     | 
    
         
            +
                    should raise_error ArgumentError, %r{should be an SMG::Model or a valid typecast}
         
     | 
| 
      
 120 
     | 
    
         
            +
                  end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                end
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
                describe "with :context option" do
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                  it "defaults @context to nil, if :context is an empty Array" do
         
     | 
| 
      
 127 
     | 
    
         
            +
                    e = SMG::Mapping::Element.new(['node'], :context => [])
         
     | 
| 
      
 128 
     | 
    
         
            +
                    e.context.should be_nil
         
     | 
| 
      
 129 
     | 
    
         
            +
                  end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                  it "removes duplicates from @context" do
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
                    e = SMG::Mapping::Element.new(['node'], :context => [:foo, :bar, :baz])
         
     | 
| 
      
 134 
     | 
    
         
            +
                    e.context.should == [:foo, :bar, :baz]
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                    e = SMG::Mapping::Element.new(['node'], :context => [:foo, :bar, :foo, :bar, :baz, :baz])
         
     | 
| 
      
 137 
     | 
    
         
            +
                    e.context.should == [:foo, :bar, :baz]
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
                    # undestructive
         
     | 
| 
      
 140 
     | 
    
         
            +
                    cct = [:foo, :foo, :bar]
         
     | 
| 
      
 141 
     | 
    
         
            +
                    e = SMG::Mapping::Element.new(['node','subnode'], :context => cct)
         
     | 
| 
      
 142 
     | 
    
         
            +
                    cct.should == [:foo, :foo, :bar]
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
                  end
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                  it "raises an ArgumentError, if :context is not an Array of Symbols" do
         
     | 
| 
      
 147 
     | 
    
         
            +
                    lambda { e = SMG::Mapping::Element.new(['node'], :context => "something") }.
         
     | 
| 
      
 148 
     | 
    
         
            +
                    should raise_error ArgumentError, %r{should be an Array of Symbols}
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                    lambda { e = SMG::Mapping::Element.new(['node'], :context => [42]) }.
         
     | 
| 
      
 151 
     | 
    
         
            +
                    should raise_error ArgumentError, %r{should be an Array of Symbols}
         
     | 
| 
      
 152 
     | 
    
         
            +
                  end
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
                end
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
              end
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
              describe "#collection?" do
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
                it "returns true if Element is a collection" do
         
     | 
| 
      
 161 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','subnode'], :collection => true)
         
     | 
| 
      
 162 
     | 
    
         
            +
                  e.should be_a_collection
         
     | 
| 
      
 163 
     | 
    
         
            +
                end
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
      
 165 
     | 
    
         
            +
                it "returns false otherwise" do
         
     | 
| 
      
 166 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','subnode'])
         
     | 
| 
      
 167 
     | 
    
         
            +
                  e.should_not be_a_collection
         
     | 
| 
      
 168 
     | 
    
         
            +
                end
         
     | 
| 
      
 169 
     | 
    
         
            +
             
     | 
| 
      
 170 
     | 
    
         
            +
              end
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
              describe "#cast" do
         
     | 
| 
      
 173 
     | 
    
         
            +
             
     | 
| 
      
 174 
     | 
    
         
            +
                it "does nothing if there's no @cast_to" do
         
     | 
| 
      
 175 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node'])
         
     | 
| 
      
 176 
     | 
    
         
            +
                  thing = "42"
         
     | 
| 
      
 177 
     | 
    
         
            +
                  e.cast(thing).should be_eql thing
         
     | 
| 
      
 178 
     | 
    
         
            +
                end
         
     | 
| 
      
 179 
     | 
    
         
            +
             
     | 
| 
      
 180 
     | 
    
         
            +
                it "performs the typecast otherwise" do
         
     | 
| 
      
 181 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node'], :class => :integer)
         
     | 
| 
      
 182 
     | 
    
         
            +
                  thing = "42"
         
     | 
| 
      
 183 
     | 
    
         
            +
                  SMG::Mapping::TypeCasts.should_receive(:[]).with(:integer, thing).and_return("42 (typecasted)")
         
     | 
| 
      
 184 
     | 
    
         
            +
                  e.cast(thing).should == "42 (typecasted)"
         
     | 
| 
      
 185 
     | 
    
         
            +
                end
         
     | 
| 
      
 186 
     | 
    
         
            +
             
     | 
| 
      
 187 
     | 
    
         
            +
                it "raises an ArgumentError if typecasting fails" do
         
     | 
| 
      
 188 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node'], :class => :datetime)
         
     | 
| 
      
 189 
     | 
    
         
            +
                  lambda { e.cast('42') }.
         
     | 
| 
      
 190 
     | 
    
         
            +
                  should raise_error ArgumentError, %r{"42" is not a valid source for :datetime}
         
     | 
| 
      
 191 
     | 
    
         
            +
                end
         
     | 
| 
      
 192 
     | 
    
         
            +
             
     | 
| 
      
 193 
     | 
    
         
            +
              end
         
     | 
| 
      
 194 
     | 
    
         
            +
             
     | 
| 
      
 195 
     | 
    
         
            +
              describe "#in_context_of?" do
         
     | 
| 
      
 196 
     | 
    
         
            +
             
     | 
| 
      
 197 
     | 
    
         
            +
                it "returns true if @context of an Element is a nil" do
         
     | 
| 
      
 198 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','subnode'])
         
     | 
| 
      
 199 
     | 
    
         
            +
                  e.context.should == nil
         
     | 
| 
      
 200 
     | 
    
         
            +
                  e.in_context_of?(:whatever).should == true
         
     | 
| 
      
 201 
     | 
    
         
            +
                end
         
     | 
| 
      
 202 
     | 
    
         
            +
             
     | 
| 
      
 203 
     | 
    
         
            +
                it "returns true if @context of an Element includes context" do
         
     | 
| 
      
 204 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','subnode'], :context => [:foo])
         
     | 
| 
      
 205 
     | 
    
         
            +
                  e.context.should == [:foo]
         
     | 
| 
      
 206 
     | 
    
         
            +
                  e.in_context_of?(:foo).should == true
         
     | 
| 
      
 207 
     | 
    
         
            +
                end
         
     | 
| 
      
 208 
     | 
    
         
            +
             
     | 
| 
      
 209 
     | 
    
         
            +
                it "returns false otherwise" do
         
     | 
| 
      
 210 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','subnode'], :context => [:foo])
         
     | 
| 
      
 211 
     | 
    
         
            +
                  e.context.should == [:foo]
         
     | 
| 
      
 212 
     | 
    
         
            +
                  e.in_context_of?(:bar).should == false
         
     | 
| 
      
 213 
     | 
    
         
            +
                end
         
     | 
| 
      
 214 
     | 
    
         
            +
             
     | 
| 
      
 215 
     | 
    
         
            +
              end
         
     | 
| 
      
 216 
     | 
    
         
            +
             
     | 
| 
      
 217 
     | 
    
         
            +
              describe "#with?" do
         
     | 
| 
      
 218 
     | 
    
         
            +
             
     | 
| 
      
 219 
     | 
    
         
            +
                it "returns true if the Hash passed contains @with" do
         
     | 
| 
      
 220 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node'], :with => {"id" => "3", "status" => "accepted"})
         
     | 
| 
      
 221 
     | 
    
         
            +
                  e.should be_with("id" => "3", "status" => "accepted")
         
     | 
| 
      
 222 
     | 
    
         
            +
                  e.should be_with("id" => "3", "status" => "accepted", "key" => "value")
         
     | 
| 
      
 223 
     | 
    
         
            +
                end
         
     | 
| 
      
 224 
     | 
    
         
            +
             
     | 
| 
      
 225 
     | 
    
         
            +
                it "returns true if there are no @with conditions" do
         
     | 
| 
      
 226 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node','subnode'])
         
     | 
| 
      
 227 
     | 
    
         
            +
                  e.with.should == nil
         
     | 
| 
      
 228 
     | 
    
         
            +
                  e.should be_with("key" => "value")
         
     | 
| 
      
 229 
     | 
    
         
            +
                end
         
     | 
| 
      
 230 
     | 
    
         
            +
             
     | 
| 
      
 231 
     | 
    
         
            +
                it "returns false otherwise" do
         
     | 
| 
      
 232 
     | 
    
         
            +
                  e = SMG::Mapping::Element.new(['node'], :with => {"id" => "3", "status" => "accepted"})
         
     | 
| 
      
 233 
     | 
    
         
            +
                  e.should_not be_with("status" => "accepted")
         
     | 
| 
      
 234 
     | 
    
         
            +
                  e.should_not be_with({})
         
     | 
| 
      
 235 
     | 
    
         
            +
                end
         
     | 
| 
      
 236 
     | 
    
         
            +
             
     | 
| 
      
 237 
     | 
    
         
            +
              end
         
     | 
| 
      
 238 
     | 
    
         
            +
             
     | 
| 
      
 239 
     | 
    
         
            +
            end
         
     | 
| 
      
 240 
     | 
    
         
            +
             
     | 
| 
      
 241 
     | 
    
         
            +
            # EOF
         
     | 
| 
         @@ -0,0 +1,52 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.expand_path File.join(File.dirname(__FILE__), '..', 'spec_helper')
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe SMG::Mapping::TypeCasts, "[]" do
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              it "raises an ArgumentError when typecast is unknown" do
         
     | 
| 
      
 6 
     | 
    
         
            +
                lambda { SMG::Mapping::TypeCasts[:bogus, "42"] }.should raise_error ArgumentError, %r{Can't typecast to :bogus}
         
     | 
| 
      
 7 
     | 
    
         
            +
              end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              it "is able to typecast (Stringable) into Fixnum" do
         
     | 
| 
      
 10 
     | 
    
         
            +
                SMG::Mapping::TypeCasts[:integer, "42"].should == 42
         
     | 
| 
      
 11 
     | 
    
         
            +
                SMG::Mapping::TypeCasts[:integer, nil ].should == 0
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              it "is able to typecast (Stringable) into Symbol" do
         
     | 
| 
      
 15 
     | 
    
         
            +
                SMG::Mapping::TypeCasts[:symbol, "something"].should == :something
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              it "is able to typecast (Stringable) into Time" do
         
     | 
| 
      
 19 
     | 
    
         
            +
                source = 'Thu Apr 15 18:16:23 +0400 2010'
         
     | 
| 
      
 20 
     | 
    
         
            +
                value = SMG::Mapping::TypeCasts[:datetime, source]
         
     | 
| 
      
 21 
     | 
    
         
            +
                value.should == Time.parse(source)
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              it "is able to typecast (Stringable) into Date" do
         
     | 
| 
      
 25 
     | 
    
         
            +
                source = 'Thu Apr 15 18:16:23 +0400 2010'
         
     | 
| 
      
 26 
     | 
    
         
            +
                value = SMG::Mapping::TypeCasts[:date, source]
         
     | 
| 
      
 27 
     | 
    
         
            +
                value.should == Date.parse(source)
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              it "is able to typecast (Stringable) into URI" do
         
     | 
| 
      
 31 
     | 
    
         
            +
                source = "http://example.org:4567/foo?bar=baz"
         
     | 
| 
      
 32 
     | 
    
         
            +
                value = SMG::Mapping::TypeCasts[:uri, source]
         
     | 
| 
      
 33 
     | 
    
         
            +
                value.should == URI.parse(source)
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              it "is able to typecast (Stringable) into Float" do
         
     | 
| 
      
 37 
     | 
    
         
            +
                SMG::Mapping::TypeCasts[  :float  , nil   ].should == 0.00
         
     | 
| 
      
 38 
     | 
    
         
            +
                SMG::Mapping::TypeCasts[  :float  , "42." ].should == 42.00
         
     | 
| 
      
 39 
     | 
    
         
            +
                SMG::Mapping::TypeCasts[  :float  , ".42" ].should == 0.42
         
     | 
| 
      
 40 
     | 
    
         
            +
                SMG::Mapping::TypeCasts[  :float  , "42"  ].should == 42.00
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
              it "is able to typecast (Stringable) into Boolean" do
         
     | 
| 
      
 44 
     | 
    
         
            +
                SMG::Mapping::TypeCasts[  :boolean  , nil         ].should == nil
         
     | 
| 
      
 45 
     | 
    
         
            +
                SMG::Mapping::TypeCasts[  :boolean  , "true"      ].should == true
         
     | 
| 
      
 46 
     | 
    
         
            +
                SMG::Mapping::TypeCasts[  :boolean  , "something" ].should == true
         
     | 
| 
      
 47 
     | 
    
         
            +
                SMG::Mapping::TypeCasts[  :boolean  , "false"     ].should == false
         
     | 
| 
      
 48 
     | 
    
         
            +
              end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
            end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
            # EOF
         
     | 
| 
         @@ -0,0 +1,30 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.expand_path File.join(File.dirname(__FILE__), 'spec_helper')
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe SMG::Resource do
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              before :each do
         
     | 
| 
      
 6 
     | 
    
         
            +
                @klass = Class.new { include SMG::Resource }
         
     | 
| 
      
 7 
     | 
    
         
            +
              end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              describe "when included" do
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                it "extends class with the SMG::Model" do
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @klass.should be_an SMG::Model
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              describe "#parsed!" do
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                it "marks resource as parsed" do
         
     | 
| 
      
 20 
     | 
    
         
            +
                  resource = @klass.new
         
     | 
| 
      
 21 
     | 
    
         
            +
                  resource.should_not be_parsed
         
     | 
| 
      
 22 
     | 
    
         
            +
                  resource.parsed!
         
     | 
| 
      
 23 
     | 
    
         
            +
                  resource.should be_parsed
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
            end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            # EOF
         
     |