api_recipes 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YjgxODFjMzU4NzQwMjdkMWEyYTBlMmY1NWFjZTFkNmUwMTZhZDY5MQ==
4
+ NzgxYTlmYWEyYzMyNmYyZTY1YWIwNTgxMDhjZDdkNDZmMTgzYzRjZQ==
5
5
  data.tar.gz: !binary |-
6
- MzljOTgzNWUxNDYyOTZhYjljMGYzM2FkZWY5YzI0NjQwYTU2ZWI5OQ==
6
+ NjkwYjAyNmI5MjU4YzQ1MTI1NjNkYWRmOGQxNmFmMzBiYzk4OTNhNQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZThhMzdmYTY0YWNmZDU3NDVmN2M4ZTQ1YzhkYTQ5MTA0MWU4OGY2ZGFlM2Nj
10
- Y2JmN2Y3MmIwNDM2YjY3MTc0NWEyYzc1ODVlZWYzNDk4NDI5YmI5OGIxOTRm
11
- ZmIzYmViNWI1YzU4MjA1YmZkMjE5NzFlYmJiMjQxY2EzMGM5MjU=
9
+ Y2EzMWViY2NmNzQ5MmNmNmU0MWJiNWI2Mzk3M2ZiNWU0YjhhYzlhYjFiOTlh
10
+ M2RjOTNjMDBlZjIzOTlmMDQ3MzUzZDkwMjk5ODg4NDA0NWY5NTQxYTQ2Mzk1
11
+ NDk1ZmJlYjZiMDE5OTljMmIzZWVhMzM3MGQ5NDdjNGFmMWNjZWM=
12
12
  data.tar.gz: !binary |-
13
- Mjc0Y2MyNzFkNTY4Y2FjZjJmNWIwOTNjYmI0MmNmMWNhN2E0NjY3ZDUwNzU1
14
- YjRhZmZmNjExZTZkNzg0N2Y0NzdkZjVjMzhhMGJkNzUzNGY0OWFkNDlmMDlk
15
- YTg4ZTNlMGM5Zjg3MmRhZmM1YTE4NTgwMTI5NDExOTc3NDM2MmM=
13
+ MDVlMjViMjc2NzJiMGJhODdmMzMxNDk4NWMyMDEyNGU0YTYwZWViNjBjZWE3
14
+ NjA0MTNmYmI0ODFkNGZkMDNkNTBjOTYxZjkzYmUzOTJiODUzMDdkNmNjOTQz
15
+ MjgwYTkxOTAzMzgyNmQ2MTA3MGRjZjdiNDBhZmFiZmJjYzE1M2Q=
data/api_recipes.gemspec CHANGED
@@ -20,6 +20,5 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_dependency 'oj', '~> 2.13.0'
22
22
  spec.add_dependency 'oj_mimic_json', '~> 1.0.1'
23
- spec.add_dependency 'http', '~> 0.9.0'
24
- spec.add_dependency 'activesupport', '>= 4.0.0'
23
+ spec.add_dependency 'http', '~> 1.0.0'
25
24
  end
@@ -10,10 +10,6 @@ end
10
10
  # Let's create a simple class that uses ApiRecipes
11
11
  class MyFancyClass
12
12
  include ApiRecipes
13
-
14
- # Declare the endpoints that we're going to use
15
- # Add some custom configs
16
- endpoint :github
17
13
  end
18
14
 
19
15
 
@@ -22,6 +18,7 @@ end
22
18
 
23
19
  # Get user's usernames from Github's Apis (https://github.com)
24
20
  usernames = nil
21
+
25
22
  MyFancyClass.github.users.list do |users|
26
23
  usernames = users.collect{ |user| user['login'] }
27
24
  end
@@ -1,22 +1,23 @@
1
1
  module ApiRecipes
2
2
  class Endpoint
3
3
 
4
- attr_accessor :name, :settings, :authorization, :basic_auth
4
+ attr_accessor :name, :configs, :authorization, :basic_auth
5
5
  attr_reader :resources
6
6
 
7
- def initialize(name, config)
7
+ def initialize(name, configs)
8
8
  @name = name
9
- @config = config
10
- @settings = ApiRecipes::Settings::DEFAULT.merge config.endpoints_configs[name]
9
+ @configs = ApiRecipes::Settings::DEFAULT.merge configs
11
10
 
12
11
  # Generate some_endpoint.some_resource methods
13
12
  # e.g. github.users
14
13
  @resources = [] unless @resources
15
- @settings[:routes].each do |resource, routes|
14
+ @configs[:routes].each do |resource, routes|
16
15
  @resources << resource
17
16
  res = Resource.new resource, self, routes
18
- define_singleton_method resource do
19
- res
17
+ unless respond_to? resource
18
+ define_singleton_method resource do
19
+ res
20
+ end
20
21
  end
21
22
  end
22
23
  end
@@ -139,7 +139,7 @@ module ApiRecipes
139
139
  end
140
140
 
141
141
  def settings
142
- @endpoint.settings
142
+ @endpoint.configs
143
143
  end
144
144
 
145
145
  def start_request(route, route_attributes, *pars)
@@ -15,7 +15,7 @@ module ApiRecipes
15
15
  }
16
16
 
17
17
  DEFAULT_ROUTE_ATTRIBUTES = {
18
- method: :get
18
+ method: :get
19
19
  }
20
20
 
21
21
  AVAILABLE_PARAMS_ENCODINGS = %w(form params json body)
@@ -0,0 +1,185 @@
1
+ class Hash
2
+ # Returns a new hash with all keys converted using the block operation.
3
+ #
4
+ # hash = { name: 'Rob', age: '28' }
5
+ #
6
+ # hash.transform_keys{ |key| key.to_s.upcase }
7
+ # # => {"NAME"=>"Rob", "AGE"=>"28"}
8
+ def transform_keys
9
+ return enum_for(:transform_keys) unless block_given?
10
+ result = self.class.new
11
+ each_key do |key|
12
+ result[yield(key)] = self[key]
13
+ end
14
+ result
15
+ end
16
+
17
+ # Destructively convert all keys using the block operations.
18
+ # Same as transform_keys but modifies +self+.
19
+ def transform_keys!
20
+ return enum_for(:transform_keys!) unless block_given?
21
+ keys.each do |key|
22
+ self[yield(key)] = delete(key)
23
+ end
24
+ self
25
+ end
26
+
27
+ # Returns a new hash with all keys converted to strings.
28
+ #
29
+ # hash = { name: 'Rob', age: '28' }
30
+ #
31
+ # hash.stringify_keys
32
+ # # => {"name"=>"Rob", "age"=>"28"}
33
+ def stringify_keys
34
+ transform_keys{ |key| key.to_s }
35
+ end
36
+
37
+ # Destructively convert all keys to strings. Same as
38
+ # +stringify_keys+, but modifies +self+.
39
+ def stringify_keys!
40
+ transform_keys!{ |key| key.to_s }
41
+ end
42
+
43
+ # Returns a new hash with all keys converted to symbols, as long as
44
+ # they respond to +to_sym+.
45
+ #
46
+ # hash = { 'name' => 'Rob', 'age' => '28' }
47
+ #
48
+ # hash.symbolize_keys
49
+ # # => {:name=>"Rob", :age=>"28"}
50
+ def symbolize_keys
51
+ transform_keys{ |key| key.to_sym rescue key }
52
+ end
53
+ alias_method :to_options, :symbolize_keys
54
+
55
+ # Destructively convert all keys to symbols, as long as they respond
56
+ # to +to_sym+. Same as +symbolize_keys+, but modifies +self+.
57
+ def symbolize_keys!
58
+ transform_keys!{ |key| key.to_sym rescue key }
59
+ end
60
+ alias_method :to_options!, :symbolize_keys!
61
+
62
+ # Validate all keys in a hash match <tt>*valid_keys</tt>, raising
63
+ # ArgumentError on a mismatch.
64
+ #
65
+ # Note that keys are treated differently than HashWithIndifferentAccess,
66
+ # meaning that string and symbol keys will not match.
67
+ #
68
+ # { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key: :years. Valid keys are: :name, :age"
69
+ # { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age') # => raises "ArgumentError: Unknown key: :name. Valid keys are: 'name', 'age'"
70
+ # { name: 'Rob', age: '28' }.assert_valid_keys(:name, :age) # => passes, raises nothing
71
+ def assert_valid_keys(*valid_keys)
72
+ valid_keys.flatten!
73
+ each_key do |k|
74
+ unless valid_keys.include?(k)
75
+ raise ArgumentError.new("Unknown key: #{k.inspect}. Valid keys are: #{valid_keys.map(&:inspect).join(', ')}")
76
+ end
77
+ end
78
+ end
79
+
80
+ # Returns a new hash with all keys converted by the block operation.
81
+ # This includes the keys from the root hash and from all
82
+ # nested hashes and arrays.
83
+ #
84
+ # hash = { person: { name: 'Rob', age: '28' } }
85
+ #
86
+ # hash.deep_transform_keys{ |key| key.to_s.upcase }
87
+ # # => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}}
88
+ def deep_transform_keys(&block)
89
+ _deep_transform_keys_in_object(self, &block)
90
+ end
91
+
92
+ # Destructively convert all keys by using the block operation.
93
+ # This includes the keys from the root hash and from all
94
+ # nested hashes and arrays.
95
+ def deep_transform_keys!(&block)
96
+ _deep_transform_keys_in_object!(self, &block)
97
+ end
98
+
99
+ # Returns a new hash with all keys converted to strings.
100
+ # This includes the keys from the root hash and from all
101
+ # nested hashes and arrays.
102
+ #
103
+ # hash = { person: { name: 'Rob', age: '28' } }
104
+ #
105
+ # hash.deep_stringify_keys
106
+ # # => {"person"=>{"name"=>"Rob", "age"=>"28"}}
107
+ def deep_stringify_keys
108
+ deep_transform_keys{ |key| key.to_s }
109
+ end
110
+
111
+ # Destructively convert all keys to strings.
112
+ # This includes the keys from the root hash and from all
113
+ # nested hashes and arrays.
114
+ def deep_stringify_keys!
115
+ deep_transform_keys!{ |key| key.to_s }
116
+ end
117
+
118
+ # Returns a new hash with all keys converted to symbols, as long as
119
+ # they respond to +to_sym+. This includes the keys from the root hash
120
+ # and from all nested hashes and arrays.
121
+ #
122
+ # hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } }
123
+ #
124
+ # hash.deep_symbolize_keys
125
+ # # => {:person=>{:name=>"Rob", :age=>"28"}}
126
+ def deep_symbolize_keys
127
+ deep_transform_keys{ |key| key.to_sym rescue key }
128
+ end
129
+
130
+ # Destructively convert all keys to symbols, as long as they respond
131
+ # to +to_sym+. This includes the keys from the root hash and from all
132
+ # nested hashes and arrays.
133
+ def deep_symbolize_keys!
134
+ deep_transform_keys!{ |key| key.to_sym rescue key }
135
+ end
136
+
137
+ private
138
+ # support methods for deep transforming nested hashes and arrays
139
+ def _deep_transform_keys_in_object(object, &block)
140
+ case object
141
+ when Hash
142
+ object.each_with_object({}) do |(key, value), result|
143
+ result[yield(key)] = _deep_transform_keys_in_object(value, &block)
144
+ end
145
+ when Array
146
+ object.map {|e| _deep_transform_keys_in_object(e, &block) }
147
+ else
148
+ object
149
+ end
150
+ end
151
+
152
+ def _deep_transform_keys_in_object!(object, &block)
153
+ case object
154
+ when Hash
155
+ object.keys.each do |key|
156
+ value = object.delete(key)
157
+ object[yield(key)] = _deep_transform_keys_in_object!(value, &block)
158
+ end
159
+ object
160
+ when Array
161
+ object.map! {|e| _deep_transform_keys_in_object!(e, &block)}
162
+ else
163
+ object
164
+ end
165
+ end
166
+ end
167
+
168
+ class Array
169
+ # Extracts options from a set of arguments. Removes and returns the last
170
+ # element in the array if it's a hash, otherwise returns a blank hash.
171
+ #
172
+ # def options(*args)
173
+ # args.extract_options!
174
+ # end
175
+ #
176
+ # options(1, 2) # => {}
177
+ # options(1, 2, a: :b) # => {:a=>:b}
178
+ def extract_options!
179
+ if last.is_a?(Hash)
180
+ pop
181
+ else
182
+ {}
183
+ end
184
+ end
185
+ end
@@ -1,3 +1,3 @@
1
1
  module ApiRecipes
2
- VERSION = '0.0.2'
2
+ VERSION = '0.0.3'
3
3
  end
data/lib/api_recipes.rb CHANGED
@@ -1,26 +1,41 @@
1
1
  require 'http'
2
2
  require 'oj'
3
3
  require 'oj_mimic_json'
4
- require 'active_support/core_ext/hash/indifferent_access'
5
- require 'active_support/core_ext/hash/keys'
6
- require 'active_support/core_ext/array/extract_options'
7
4
 
5
+ require 'api_recipes/utils'
8
6
  require 'api_recipes/exceptions'
9
7
  require 'api_recipes/configuration'
10
8
  require 'api_recipes/resource'
11
9
  require 'api_recipes/endpoint'
12
10
  require 'api_recipes/settings'
13
11
 
12
+ HTTP.inspect
13
+
14
14
  module ApiRecipes
15
15
 
16
16
  def self.included(base)
17
- base.send :include, InstanceAndClassMethods
18
- base.extend ClassMethods
19
- base.extend InstanceAndClassMethods
20
- end
21
17
 
22
- class << self
23
- attr_accessor :configuration
18
+ def base.endpoint(endpoint_name, configs, obj = nil)
19
+ overwrite = false
20
+ # If no obj has given, do not overwrite the EP (i.e. use the one created on configuration phase)
21
+ # Else ff an obj has given, overwrite the EP with a new EP with new configs.
22
+ # This EP will be accessible by this obj only (both class and instance)
23
+ unless obj
24
+ obj = self
25
+ overwrite = true
26
+ end
27
+ configs = ApiRecipes._aprcps_merge_endpoints_configs(endpoint_name, configs.deep_symbolize_keys)
28
+ endpoint_name = endpoint_name.to_sym
29
+
30
+ # Define 'endpoint_name' method for the class
31
+ ApiRecipes._aprcps_define_class_endpoint endpoint_name, configs, obj, overwrite
32
+ # Define 'endpoint_name' method for the class' instances
33
+ ApiRecipes._aprcps_define_instance_endpoint endpoint_name, obj
34
+ end
35
+
36
+ configuration.endpoints_configs.each do |endpoint_name, endpoint_configs|
37
+ base.endpoint endpoint_name, endpoint_configs, base
38
+ end
24
39
  end
25
40
 
26
41
  def self.configuration
@@ -33,58 +48,63 @@ module ApiRecipes
33
48
  def self.configure
34
49
  if block_given?
35
50
  yield(configuration)
51
+ _aprcps_define_global_endpoints
36
52
  else
37
53
  configuration
38
54
  end
39
55
  end
40
56
 
41
- module ClassMethods
42
- def endpoint(name, configs = {})
43
- configs = configs.deep_symbolize_keys
44
- name = name.to_sym
45
-
46
- ep = Endpoint.new(name, merge_endpoints_configs(name, configs))
47
- # Define 'name' method for the class
48
- define_class_endpoint ep
49
- # Define 'name' method for the class' instances
50
- define_instance_endpoint ep
57
+ def self._aprcps_define_global_endpoints
58
+ configuration.endpoints_configs.each do |endpoint_name, endpoint_configs|
59
+ unless method_defined? endpoint_name
60
+ unless _aprcps_storage[endpoint_name]
61
+ _aprcps_storage[endpoint_name] = Endpoint.new endpoint_name, endpoint_configs
62
+ end
63
+ define_singleton_method endpoint_name do
64
+ _aprcps_storage[endpoint_name]
65
+ end
66
+ end
51
67
  end
68
+ end
52
69
 
53
- private
70
+ def self._aprcps_storage
71
+ unless Thread.current[:api_recipes]
72
+ Thread.current[:api_recipes] = {}
73
+ end
74
+ Thread.current[:api_recipes]
75
+ end
54
76
 
55
- def define_class_endpoint(ep)
56
- name = ep.name
57
- unless method_defined? name
58
- Thread.current[name] = ep
59
77
 
60
- define_singleton_method name do
61
- Thread.current[name]
62
- end
78
+ def self._aprcps_define_class_endpoint(ep_name, configs, obj, overwrite)
79
+ unless obj.method_defined? ep_name
80
+ if overwrite
81
+ ep = Endpoint.new(ep_name, configs)
82
+ else
83
+ ep = _aprcps_storage[ep_name]
84
+ end
85
+ obj.define_singleton_method ep_name do
86
+ ep
63
87
  end
64
88
  end
89
+ end
65
90
 
66
- def define_instance_endpoint(ep)
67
- name = ep.name
68
- send :define_method, name do
69
- Thread.current[name].clone
91
+ def self._aprcps_define_instance_endpoint(ep_name, obj)
92
+ obj.instance_eval do
93
+ unless obj.method_defined? ep_name
94
+ define_method ep_name do
95
+ self.class.send ep_name
96
+ end
70
97
  end
71
98
  end
72
99
  end
73
100
 
74
- module InstanceAndClassMethods
75
-
76
- private
77
-
78
- def merge_endpoints_configs(endpoint, configs)
79
- if configs && !configs.is_a?(Hash)
80
- raise EndpointConfigIsNotAnHash.new(endpoint)
81
- end
82
- unless ApiRecipes.configuration.endpoints_configs[endpoint]
83
- ApiRecipes.configuration.endpoints_configs[endpoint] = {}
84
- end
85
- ApiRecipes.configuration.endpoints_configs[endpoint].merge! configs
86
- ApiRecipes.configuration
101
+ def self._aprcps_merge_endpoints_configs(endpoint_name, configs)
102
+ if configs && !configs.is_a?(Hash)
103
+ raise ApiRecipes::EndpointConfigIsNotAnHash.new(endpoint_name)
104
+ end
105
+ unless ApiRecipes.configuration.endpoints_configs[endpoint_name]
106
+ ApiRecipes.configuration.endpoints_configs[endpoint_name] = {}
87
107
  end
108
+ ApiRecipes.configuration.endpoints_configs[endpoint_name].merge configs
88
109
  end
89
110
  end
90
-
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: api_recipes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alessandro Verlato
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-23 00:00:00.000000000 Z
11
+ date: 2016-02-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oj
@@ -44,28 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - ~>
46
46
  - !ruby/object:Gem::Version
47
- version: 0.9.0
47
+ version: 1.0.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ~>
53
53
  - !ruby/object:Gem::Version
54
- version: 0.9.0
55
- - !ruby/object:Gem::Dependency
56
- name: activesupport
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ! '>='
60
- - !ruby/object:Gem::Version
61
- version: 4.0.0
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ! '>='
67
- - !ruby/object:Gem::Version
68
- version: 4.0.0
54
+ version: 1.0.0
69
55
  description:
70
56
  email:
71
57
  - averlato@gmail.com
@@ -100,6 +86,7 @@ files:
100
86
  - lib/api_recipes/exceptions.rb
101
87
  - lib/api_recipes/resource.rb
102
88
  - lib/api_recipes/settings.rb
89
+ - lib/api_recipes/utils.rb
103
90
  - lib/api_recipes/version.rb
104
91
  homepage: https://github.com/madAle/api_recipes
105
92
  licenses: