spitter 0.0.1

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/.gitignore ADDED
@@ -0,0 +1,24 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ *.gem
5
+ dist
6
+ .yardopts
7
+ .yardoc
8
+
9
+ ## TEXTMATE
10
+ *.tmproj
11
+ tmtags
12
+
13
+ ## EMACS
14
+ *~
15
+ \#*
16
+ .\#*
17
+
18
+ ## VIM
19
+ *.swp
20
+
21
+ ## PROJECT::GENERAL
22
+ coverage
23
+ rdoc
24
+ pkg
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
6
+ script: bundle exec rspec spec
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :rubygems
2
+
3
+ # Specify your gem's dependencies in spitter.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,25 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ spitter (0.0.1)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.1.3)
10
+ rspec (2.10.0)
11
+ rspec-core (~> 2.10.0)
12
+ rspec-expectations (~> 2.10.0)
13
+ rspec-mocks (~> 2.10.0)
14
+ rspec-core (2.10.1)
15
+ rspec-expectations (2.10.0)
16
+ diff-lcs (~> 1.1.3)
17
+ rspec-mocks (2.10.1)
18
+
19
+ PLATFORMS
20
+ ruby
21
+
22
+ DEPENDENCIES
23
+ bundler (>= 1.0.0)
24
+ rspec (~> 2.6)
25
+ spitter!
data/README.rdoc ADDED
@@ -0,0 +1,83 @@
1
+ = Spitter {<img src="https://secure.travis-ci.org/bonsaiben/spitter.png">}[http://travis-ci.org/bonsaiben/spitter] {<img src="https://gemnasium.com/bonsaiben/spitter.png">}[https://gemnasium.com/bonsaiben/spitter]
2
+
3
+ Takes nice Ruby parameter hashes and spits out whatever crap you need it to. A simple way to provide a custom Ruby interface for the request side of an API wrapper. Based on @mislav's nibbler[https://github.com/mislav/nibbler].
4
+
5
+
6
+ == Installation
7
+
8
+ gem install spitter
9
+
10
+
11
+ == Example Usage
12
+
13
+ === Transform Key
14
+
15
+ class ApiClient < Spitter
16
+ parameter :ruby_param => 'apiCamelCaseDataFlag'
17
+ end
18
+
19
+ $ ApiClient.parse(:purchasable => '1')
20
+ => {'apiCamelCaseDataFlag' => '1'}
21
+
22
+ === Transform Value with Lambda
23
+
24
+ class ApiClient < Spitter
25
+ parameter :ruby_param => 'apiCamelCaseDataFlag', :with => lambda {|v| v ? '1' : '0'}
26
+ end
27
+
28
+ $ ApiClient.parse(:purchasable => true)
29
+ => {'apiCamelCaseDataFlag' => '1'}
30
+
31
+ === Transform Value with Class
32
+
33
+ class ApiClient < Spitter
34
+ class TrueOrFalse
35
+ def self.parse(val)
36
+ val ? '1' : '0'
37
+ end
38
+ end
39
+
40
+ parameter :ruby_param => 'apiCamelCaseDataFlag', :with => TrueOrFalse
41
+ end
42
+
43
+ $ ApiClient.parse(:purchasable => true)
44
+ => {'apiCamelCaseDataFlag' => '1'}
45
+
46
+ === Transform Value Only
47
+
48
+ class ApiClient < Spitter
49
+ parameter :timestamp, :with => lambda{|v| v.to_i.to_s }
50
+ end
51
+
52
+ $ ApiClient.parse(:timestamp => Time.now)
53
+ => {'timestamp' => '1341162393'}
54
+
55
+ == License
56
+
57
+ (The MIT License)
58
+
59
+ Copyright (c) 2012 Benjamin Sullivan
60
+
61
+ Permission is hereby granted, free of charge, to any person obtaining
62
+ a copy of this software and associated documentation files (the
63
+ 'Software'), to deal in the Software without restriction, including
64
+ without limitation the rights to use, copy, modify, merge, publish,
65
+ distribute, sublicense, and/or sell copies of the Software, and to
66
+ permit persons to whom the Software is furnished to do so, subject to
67
+ the following conditions:
68
+
69
+ The above copyright notice and this permission notice shall be
70
+ included in all copies or substantial portions of the Software.
71
+
72
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
73
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
74
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
75
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
76
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
77
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
78
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
79
+
80
+
81
+ == Credit
82
+
83
+ Spitter is based on @mislav's nibbler[https://github.com/mislav/nibbler].
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,3 @@
1
+ class Spitter
2
+ VERSION = "0.0.1"
3
+ end
data/lib/spitter.rb ADDED
@@ -0,0 +1,101 @@
1
+ module SpitterMethods
2
+ def self.extended(base)
3
+ base.send(:include, InstanceMethods) if base.is_a? Class
4
+ end
5
+
6
+ # Declare a singular spitting rule
7
+ def parameter(*args, &block)
8
+ key, name, delegate = parse_rule_declaration(*args, &block)
9
+ rules[key] = [name, delegate]
10
+ key
11
+ end
12
+
13
+ # Declare a plural spitting rule
14
+ def parameters(*args, &block)
15
+ key = parameter(*args, &block)
16
+ rules[key] << true
17
+ end
18
+
19
+ # Parsing rules declared with `parameter` or `parameters`
20
+ def rules
21
+ @rules ||= {}
22
+ end
23
+
24
+ # Process data by creating a new instance
25
+ def parse(params) new(params).parse end
26
+
27
+ private
28
+
29
+ # Make subclasses inherit the parsing rules
30
+ def inherited(subclass)
31
+ super
32
+ subclass.rules.update self.rules
33
+ end
34
+
35
+ # Rule declaration forms:
36
+ #
37
+ # { :key => 'property', :with => delegate }
38
+ # #=> [:key, 'property', delegate]
39
+ #
40
+ # :title
41
+ # #=> [:title, 'title', nil]
42
+ def parse_rule_declaration(*args, &block)
43
+ options, name = Hash === args.last ? args.pop : {}, args.first
44
+ delegate = options.delete(:with)
45
+ key, property = name ? [name.to_sym, name.to_s] : options.to_a.flatten
46
+ property = property[key.to_s] if property.is_a?(Proc)
47
+ property = property.method(property.respond_to?(:call) ? :call : :parse)[key.to_s] if property.is_a?(Class)
48
+ raise ArgumentError, "invalid rule declaration: #{args.inspect}" unless property
49
+ # eval block in context of a new spitter subclass
50
+ delegate = Class.new(Spitter, &block) if block_given?
51
+ return key, property, delegate
52
+ end
53
+
54
+ def base_parser_class
55
+ klass = self
56
+ klass = klass.superclass until klass.superclass == Object
57
+ klass
58
+ end
59
+
60
+ module InstanceMethods
61
+
62
+ # Initialize the parser with parameters
63
+ def initialize(params)
64
+ @params = params
65
+ end
66
+
67
+ def params
68
+ @params ||= {}
69
+ end
70
+
71
+ def parse
72
+ request_params = {}
73
+ self.class.rules.each do |target, (key, delegate, plural)|
74
+ if @params.has_key?(target)
75
+ if plural
76
+ request_params.merge!(delegate.parse(@params[target]))
77
+ else
78
+ request_params[key] = parse_result(@params[target], delegate)
79
+ end
80
+ end
81
+ end
82
+ request_params
83
+ end
84
+
85
+ protected
86
+
87
+ # `delegate` is optional, but should respond to `call` or `parse`
88
+ def parse_result(node, delegate)
89
+ if delegate
90
+ method = delegate.is_a?(Proc) ? delegate : delegate.method(delegate.respond_to?(:call) ? :call : :parse)
91
+ method.arity == 1 ? method[node] : (method.arity == 2 ? method[node, self] : method[])
92
+ else
93
+ node
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ class Spitter
100
+ extend SpitterMethods
101
+ end
@@ -0,0 +1,2 @@
1
+ require 'spitter'
2
+
@@ -0,0 +1,121 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe Spitter do
5
+
6
+ context "no conversion" do
7
+ before do
8
+ @params = {:code => "1234"}
9
+ @spitter = Class.new(Spitter){ parameter :code }.new(@params)
10
+ end
11
+
12
+ it "creates the rules" do
13
+ @spitter.class.rules.should eq({:code => ['code',nil]})
14
+ end
15
+
16
+ it "transforms the params" do
17
+ new_params = @spitter.parse
18
+ new_params.should eq({'code' => '1234'})
19
+ end
20
+ end
21
+
22
+ context "simple conversion" do
23
+ before do
24
+ @params = {:item_id => 1}
25
+ @spitter = Class.new(Spitter){ parameter :item_id => 'itemId' }.new(@params)
26
+ end
27
+
28
+ it "creates the rules" do
29
+ @spitter.class.rules.should eq({:item_id => ['itemId',nil]})
30
+ end
31
+
32
+ it "transforms the params" do
33
+ new_params = @spitter.parse
34
+ new_params.should eq({'itemId' => 1})
35
+ end
36
+ end
37
+
38
+ context "proc conversion" do
39
+ before do
40
+ @params = {:item_id => 1}
41
+ @spitter = Class.new(Spitter){ parameter :item_id => lambda {|i| i.to_s.upcase }}.new(@params)
42
+ end
43
+
44
+ it "creates the rules" do
45
+ @spitter.class.rules.should eq({:item_id => ['ITEM_ID',nil]})
46
+ end
47
+
48
+ it "transforms the params" do
49
+ new_params = @spitter.parse
50
+ new_params.should eq({'ITEM_ID' => 1})
51
+ end
52
+ end
53
+
54
+ context "class conversion" do
55
+ before do
56
+ @params = {:item_id => 1}
57
+ klass = Class.new do
58
+ def self.parse val
59
+ val.upcase
60
+ end
61
+ end
62
+ @spitter = Class.new(Spitter){ parameter :item_id => klass }.new(@params)
63
+ end
64
+
65
+ it "creates the rules" do
66
+ @spitter.class.rules.should eq({:item_id => ['ITEM_ID',nil]})
67
+ end
68
+
69
+ it "transforms the params" do
70
+ new_params = @spitter.parse
71
+ new_params.should eq({'ITEM_ID' => 1})
72
+ end
73
+ end
74
+
75
+ context "value conversion with proc" do
76
+ before do
77
+ @params = {:is_cool => true}
78
+ @spitter = Class.new(Spitter){ parameter :is_cool => 'isCool', :with => lambda { |a| a ? "1" : "0" } }.new(@params)
79
+ end
80
+
81
+ it "transforms the params" do
82
+ new_params = @spitter.parse
83
+ new_params.should eq({'isCool' => '1'})
84
+ end
85
+ end
86
+
87
+ context "value conversion with class" do
88
+ before do
89
+ @params = {:is_cool => true}
90
+ klass = Class.new do
91
+ def self.parse val
92
+ val ? "1" : "0"
93
+ end
94
+ end
95
+ @spitter = Class.new(Spitter){ parameter :is_cool => 'isCool', :with => klass }.new(@params)
96
+ end
97
+
98
+ it "transforms the params" do
99
+ new_params = @spitter.parse
100
+ new_params.should eq({'isCool' => '1'})
101
+ end
102
+ end
103
+
104
+ context "nested conversion" do
105
+ before do
106
+ @params = {:shop => {:name => "roomba", :code => "123"} }
107
+ @spitter = Class.new(Spitter) do
108
+ parameters :shop do
109
+ parameter :name => 'shopName'
110
+ parameter :code => 'shopCode'
111
+ end
112
+ end.new(@params)
113
+ end
114
+
115
+ it "transforms the params" do
116
+ new_params = @spitter.parse
117
+ new_params.should eq({'shopName' => 'roomba', 'shopCode' => '123'})
118
+ end
119
+ end
120
+
121
+ end
data/spitter.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ require File.expand_path('../lib/spitter/version', __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{spitter}
5
+ s.version = Spitter::VERSION
6
+ s.platform = Gem::Platform::RUBY
7
+ s.required_rubygems_version = ">= 1.3.6"
8
+ s.authors = ["Benjamin Sullivan"]
9
+ s.email = %q{bsullivan2@gmail.com}
10
+ s.homepage = %q{http://github.com/bonsaiben/spitter}
11
+ s.summary = %q{A simple way to provide a custom Ruby interface for the request side of an API wrapper.}
12
+ s.description = %q{Takes nice Ruby parameter hashes and spits out whatever crap you need it to.}
13
+
14
+ s.required_rubygems_version = ">= 1.3.6"
15
+
16
+ s.add_development_dependency "bundler", ">= 1.0.0"
17
+ s.add_development_dependency "rspec", "~> 2.6"
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.require_path = 'lib'
21
+
22
+ end
23
+
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spitter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Benjamin Sullivan
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-01 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.0.0
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.0.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '2.6'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '2.6'
46
+ description: Takes nice Ruby parameter hashes and spits out whatever crap you need
47
+ it to.
48
+ email: bsullivan2@gmail.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .gitignore
54
+ - .travis.yml
55
+ - Gemfile
56
+ - Gemfile.lock
57
+ - README.rdoc
58
+ - Rakefile
59
+ - lib/spitter.rb
60
+ - lib/spitter/version.rb
61
+ - spec/spec_helper.rb
62
+ - spec/spitter_spec.rb
63
+ - spitter.gemspec
64
+ homepage: http://github.com/bonsaiben/spitter
65
+ licenses: []
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: 1.3.6
82
+ requirements: []
83
+ rubyforge_project:
84
+ rubygems_version: 1.8.24
85
+ signing_key:
86
+ specification_version: 3
87
+ summary: A simple way to provide a custom Ruby interface for the request side of an
88
+ API wrapper.
89
+ test_files: []
90
+ has_rdoc: