mashery_rails 0.6.2

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.
Files changed (52) hide show
  1. data/.gitignore +6 -0
  2. data/.travis.yml +12 -0
  3. data/.yardoc/checksums +17 -0
  4. data/.yardoc/object_types +0 -0
  5. data/.yardoc/objects/root.dat +0 -0
  6. data/.yardoc/proxy_types +0 -0
  7. data/Gemfile +21 -0
  8. data/Gemfile.devtools +55 -0
  9. data/Gemfile.lock +215 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +63 -0
  12. data/Rakefile +9 -0
  13. data/VERSION +1 -0
  14. data/config/devtools.yml +2 -0
  15. data/config/flay.yml +3 -0
  16. data/config/flog.yml +2 -0
  17. data/config/mutant.yml +3 -0
  18. data/config/reek.yml +103 -0
  19. data/config/rubocop.yml +58 -0
  20. data/config/yardstick.yml +2 -0
  21. data/lib/mashery.rb +55 -0
  22. data/lib/mashery/config.rb +71 -0
  23. data/lib/mashery/exceptions.rb +46 -0
  24. data/lib/mashery/key.rb +7 -0
  25. data/lib/mashery/local.rb +3 -0
  26. data/lib/mashery/member.rb +8 -0
  27. data/lib/mashery/query_builder.rb +173 -0
  28. data/lib/mashery/rails.rb +19 -0
  29. data/lib/mashery/rest_client.rb +31 -0
  30. data/lib/mashery/rest_client/query.rb +77 -0
  31. data/lib/mashery/rpc_client.rb +58 -0
  32. data/lib/mashery/rpc_client/base.rb +51 -0
  33. data/lib/mashery/rpc_client/response.rb +79 -0
  34. data/lib/mashery/service.rb +9 -0
  35. data/masheri.gemspec +26 -0
  36. data/mashery_rails.gemspec +25 -0
  37. data/spec/fixtures/config.no_host.yml +4 -0
  38. data/spec/fixtures/config.no_key.yml +4 -0
  39. data/spec/fixtures/config.no_secret.yml +4 -0
  40. data/spec/fixtures/config.no_site_id.yml +4 -0
  41. data/spec/fixtures/config.yml +5 -0
  42. data/spec/fixtures/services.json +3 -0
  43. data/spec/mashery/config_spec.rb +38 -0
  44. data/spec/mashery/member_spec.rb +47 -0
  45. data/spec/mashery/query_builder_spec.rb +13 -0
  46. data/spec/mashery/rest_client_spec.rb +47 -0
  47. data/spec/mashery/rpc_client_spec.rb +28 -0
  48. data/spec/mashery/service_spec.rb +101 -0
  49. data/spec/mashery_spec.rb +5 -0
  50. data/spec/spec_helper.rb +50 -0
  51. data/tasks/mashery.thor +200 -0
  52. metadata +147 -0
data/config/flay.yml ADDED
@@ -0,0 +1,3 @@
1
+ ---
2
+ threshold: 0
3
+ total_score: 0
data/config/flog.yml ADDED
@@ -0,0 +1,2 @@
1
+ ---
2
+ threshold: 0
data/config/mutant.yml ADDED
@@ -0,0 +1,3 @@
1
+ ---
2
+ name: your_lib
3
+ namespace: YourLib
data/config/reek.yml ADDED
@@ -0,0 +1,103 @@
1
+ ---
2
+ Attribute:
3
+ enabled: true
4
+ exclude: []
5
+ BooleanParameter:
6
+ enabled: true
7
+ exclude: []
8
+ ClassVariable:
9
+ enabled: true
10
+ exclude: []
11
+ ControlParameter:
12
+ enabled: true
13
+ exclude: []
14
+ DataClump:
15
+ enabled: true
16
+ exclude: []
17
+ max_copies: 2
18
+ min_clump_size: 2
19
+ DuplicateMethodCall:
20
+ enabled: true
21
+ exclude: []
22
+ max_calls: 1
23
+ allow_calls: []
24
+ FeatureEnvy:
25
+ enabled: true
26
+ exclude: []
27
+ IrresponsibleModule:
28
+ enabled: true
29
+ exclude: []
30
+ LongParameterList:
31
+ enabled: true
32
+ exclude: []
33
+ max_params: 2
34
+ overrides:
35
+ initialize:
36
+ max_params: 3
37
+ LongYieldList:
38
+ enabled: true
39
+ exclude: []
40
+ max_params: 2
41
+ NestedIterators:
42
+ enabled: true
43
+ exclude: []
44
+ max_allowed_nesting: 1
45
+ ignore_iterators: []
46
+ NilCheck:
47
+ enabled: true
48
+ exclude: []
49
+ RepeatedConditional:
50
+ enabled: true
51
+ exclude: []
52
+ max_ifs: 1
53
+ TooManyInstanceVariables:
54
+ enabled: true
55
+ exclude: []
56
+ max_instance_variables: 3
57
+ TooManyMethods:
58
+ enabled: true
59
+ exclude: []
60
+ max_methods: 10
61
+ TooManyStatements:
62
+ enabled: true
63
+ exclude:
64
+ - each
65
+ max_statements: 2
66
+ UncommunicativeMethodName:
67
+ enabled: true
68
+ exclude: []
69
+ reject:
70
+ - !ruby/regexp /^[a-z]$/
71
+ - !ruby/regexp /[0-9]$/
72
+ - !ruby/regexp /[A-Z]/
73
+ accept: []
74
+ UncommunicativeModuleName:
75
+ enabled: true
76
+ exclude: []
77
+ reject:
78
+ - !ruby/regexp /^.$/
79
+ - !ruby/regexp /[0-9]$/
80
+ accept: []
81
+ UncommunicativeParameterName:
82
+ enabled: true
83
+ exclude: []
84
+ reject:
85
+ - !ruby/regexp /^.$/
86
+ - !ruby/regexp /[0-9]$/
87
+ - !ruby/regexp /[A-Z]/
88
+ accept: []
89
+ UncommunicativeVariableName:
90
+ enabled: true
91
+ exclude: []
92
+ reject:
93
+ - !ruby/regexp /^.$/
94
+ - !ruby/regexp /[0-9]$/
95
+ - !ruby/regexp /[A-Z]/
96
+ accept: []
97
+ UnusedParameters:
98
+ enabled: true
99
+ exclude: []
100
+ UtilityFunction:
101
+ enabled: true
102
+ exclude: []
103
+ max_helper_calls: 0
@@ -0,0 +1,58 @@
1
+ AllCops:
2
+ Includes:
3
+ - '**/*.rake'
4
+ - 'Gemfile'
5
+ - 'Gemfile.devtools'
6
+ Excludes:
7
+ - '**/vendor/**'
8
+ - '**/benchmarks/**'
9
+
10
+ # Avoid parameter lists longer than five parameters.
11
+ ParameterLists:
12
+ Max: 3
13
+ CountKeywordArgs: true
14
+
15
+ # Avoid more than `Max` levels of nesting.
16
+ BlockNesting:
17
+ Max: 3
18
+
19
+ # Align with the style guide.
20
+ CollectionMethods:
21
+ PreferredMethods:
22
+ collect: 'map'
23
+ inject: 'reduce'
24
+ find: 'detect'
25
+ find_all: 'select'
26
+
27
+ # Do not force public/protected/private keyword to be indented at the same
28
+ # level as the def keyword. My personal preference is to outdent these keywords
29
+ # because I think when scanning code it makes it easier to identify the
30
+ # sections of code and visually separate them. When the keyword is at the same
31
+ # level I think it sort of blends in with the def keywords and makes it harder
32
+ # to scan the code and see where the sections are.
33
+ AccessControl:
34
+ Enabled: false
35
+
36
+ # Limit line length
37
+ LineLength:
38
+ Max: 79
39
+
40
+ # Disable documentation checking until a class needs to be documented once
41
+ Documentation:
42
+ Enabled: false
43
+
44
+ # Do not favor modifier if/unless usage when you have a single-line body
45
+ IfUnlessModifier:
46
+ Enabled: false
47
+
48
+ # Allow case equality operator (in limited use within the specs)
49
+ CaseEquality:
50
+ Enabled: false
51
+
52
+ # Constants do not always have to use SCREAMING_SNAKE_CASE
53
+ ConstantName:
54
+ Enabled: false
55
+
56
+ # Not all trivial readers/writers can be defined with attr_* methods
57
+ TrivialAccessors:
58
+ Enabled: false
@@ -0,0 +1,2 @@
1
+ ---
2
+ threshold: 100
data/lib/mashery.rb ADDED
@@ -0,0 +1,55 @@
1
+ $LOAD_PATH.unshift File.expand_path("./lib")
2
+
3
+ require 'active_support/core_ext'
4
+ require 'logger'
5
+ require 'digest/md5'
6
+ require 'restclient'
7
+
8
+ require 'mashery/exceptions'
9
+ require 'mashery/config'
10
+
11
+ require 'mashery/rpc_client'
12
+ require 'mashery/rpc_client/base'
13
+ require 'mashery/rpc_client/response'
14
+
15
+ require 'mashery/rest_client'
16
+ require 'mashery/query_builder'
17
+ require 'mashery/rest_client/query'
18
+
19
+
20
+ require 'mashery/member'
21
+ require 'mashery/key'
22
+ require 'mashery/service'
23
+
24
+ module Mashery
25
+ @@config = nil
26
+
27
+ def self.config
28
+ raise Mashery::ConfigMissing.new unless @@config.present?
29
+ @@config
30
+ end
31
+
32
+ def self.config=(other)
33
+ @@config = other
34
+ end
35
+
36
+ def self.load_config!(yaml_file)
37
+ Mashery.config = Mashery::Config.new(yaml_file)
38
+ end
39
+
40
+ def self.rpc
41
+ Mashery::RpcClient.new
42
+ end
43
+
44
+ def self.rest
45
+ Mashery::RestClient.new
46
+ end
47
+
48
+ def self.activity(activity_type, service_id, options)
49
+ Mashery.rest.activity(activity_type, service_id, options)
50
+ end
51
+ end
52
+
53
+ if defined?(Rails)
54
+ require 'mashery/rails'
55
+ end
@@ -0,0 +1,71 @@
1
+ module Mashery
2
+ class Config
3
+ DEFAULT_HOSTS = {
4
+ test: 'api.sandbox.mashery.com',
5
+ production: 'api.mashery.com'
6
+ }
7
+
8
+ attr_accessor :config
9
+
10
+ def initialize(yaml_file)
11
+ @config ||= YAML.load_file(yaml_file)
12
+ check_config!
13
+ end
14
+
15
+ def check_config!
16
+ if config["site_id"].blank?
17
+ raise ParamMissing.new("site_id")
18
+ end
19
+
20
+ if config["key"].blank?
21
+ raise ParamMissing.new("key")
22
+ end
23
+
24
+ if config["secret"].blank?
25
+ raise ParamMissing.new("secret")
26
+ end
27
+
28
+ find_host!
29
+ end
30
+
31
+ def site_id
32
+ @site_id ||= config["site_id"]
33
+ end
34
+
35
+ def key
36
+ @key ||= config["key"]
37
+ end
38
+
39
+ alias :api_key :key
40
+
41
+ def secret
42
+ @secret ||= config["secret"]
43
+ end
44
+
45
+ def host
46
+ @host ||= find_host!
47
+ end
48
+
49
+ def signature
50
+ Digest::MD5.hexdigest(key + secret + Time.now.to_f.to_i.to_s)
51
+ end
52
+
53
+ protected
54
+
55
+ def find_host!
56
+ if config["host"].present?
57
+ config["host"]
58
+ else
59
+ if defined?(Rails)
60
+ if Rails.env.test? || Rails.env.development?
61
+ DEFAULT_HOSTS[:test]
62
+ elsif Rails.env.production?
63
+ DEFAULT_HOSTS[:production]
64
+ end
65
+ end
66
+
67
+ raise ParamMissing.new("host")
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,46 @@
1
+ module Mashery
2
+ class NoClassGiven < Exception
3
+ def initialize
4
+ super("Cannot create new instance for query builder because class was not given!")
5
+ end
6
+ end
7
+
8
+ class InvalidDateRange < Exception
9
+ def initialize(start_date, end_date)
10
+ days = ((end_date - start_date) / 1.day).ceil
11
+
12
+ super("Your start_date and end_date are #{days} days apart. Mashery's API does not like date ranges that span longer than 7 days. Please use multiple queries to gather your data.")
13
+ end
14
+ end
15
+
16
+ class QueryParamMissing < Exception
17
+ def initialize(param)
18
+ super "Couldn't complete request. The query param #{param.inspect} is missing."
19
+ end
20
+ end
21
+
22
+ class ParamMissing < Exception
23
+ def initialize(param)
24
+ super "Couldn't determine Mashery #{param.inspect}! Please check your config/masheri.yml"
25
+ end
26
+ end
27
+
28
+ class ConfigMissing < Exception
29
+ def initialize
30
+ super "No configuration has been loaded! Please call Mashery.load_config! with a valid Yaml file."
31
+ end
32
+ end
33
+
34
+ class MissingConfig < Exception
35
+ def initialize
36
+ super("Couldn't find config/mashery.yml! \n" +
37
+ "Please run `rails g mashery:install` to create one and populate it with the necessary API credentials.")
38
+ end
39
+ end
40
+
41
+ class UnknownFormat < Exception
42
+ def initialize(format)
43
+ super "Unknown format #{format.inspect} for REST API call. Standard formats are CSV and JSON."
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,7 @@
1
+ module Mashery
2
+ class Key < RpcClient::Base
3
+ attr_accessor(:id, :created, :updated, :service_key, :apikey, :username, :status,
4
+ :rate_limit_ceiling, :qps_limit_ceiling, :rate_limit_exempt, :qps_limit_exempt,
5
+ :required_referer, :secret, :limits, :object_type)
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+
2
+
3
+
@@ -0,0 +1,8 @@
1
+ module Mashery
2
+ class Member < RpcClient::Base
3
+ attr_accessor(:created, :updated, :username, :email, :display_name,
4
+ :uri, :blog, :im, :imsvc, :phone, :company, :address1, :address2,
5
+ :locality, :region, :postal_code, :country_code, :first_name, :last_name,
6
+ :registration_ipaddr, :area_status, :external_id, :passwd_new, :object_type)
7
+ end
8
+ end
@@ -0,0 +1,173 @@
1
+ module Mashery
2
+ class QueryBuilder
3
+ def initialize(klass = nil, options = {})
4
+ @klass = klass
5
+ @options = options
6
+ @conditions = Where.new
7
+ @select = Select.new
8
+ end
9
+
10
+ def select(argument)
11
+ @select = Select.new(argument)
12
+ clone
13
+ end
14
+
15
+ def from(argument)
16
+ @from = From.new(argument)
17
+ clone
18
+ end
19
+
20
+ def where(argument)
21
+ @conditions.add argument
22
+ clone
23
+ end
24
+
25
+ def order(column, order)
26
+ @order = Order.new(column, order)
27
+ clone
28
+ end
29
+
30
+ def items(argument)
31
+ @items = Items.new(argument)
32
+ clone
33
+ end
34
+
35
+ def page(argument)
36
+ @page = Page.new(argument)
37
+ clone
38
+ end
39
+
40
+ def query
41
+ [@select, @from, @order, @conditions, @page, @items].map(&:to_s).reject {|s|
42
+ s.blank?
43
+ }.compact.join(" ").strip
44
+ end
45
+
46
+ def reify(*args)
47
+ raise NoClassGiven.new if @klass.blank?
48
+ @klass.new(*args)
49
+ end
50
+
51
+ alias :to_s :query
52
+
53
+ def to_json
54
+ Mashery.rpc.query(query)
55
+ end
56
+
57
+ def all
58
+ Mashery::RpcClient::Response.new(self)
59
+ end
60
+
61
+ def find_each(&block)
62
+ Mashery::RpcClient::Response.new(self).find_each(&block)
63
+ end
64
+
65
+ def first
66
+ Mashery::RpcClient::Response.new(items(1)).to_objects.first
67
+ end
68
+
69
+ protected
70
+
71
+ class Select
72
+ def initialize(argument = nil)
73
+ @argument = argument
74
+ end
75
+
76
+ def query
77
+ @argument || "*"
78
+ end
79
+
80
+ def to_s
81
+ "SELECT #{query}"
82
+ end
83
+ end
84
+
85
+ class From
86
+ def initialize(argument)
87
+ @argument = argument
88
+ end
89
+
90
+ def to_s
91
+ raise MissingFrom.new if @argument.nil?
92
+ "FROM #{@argument}"
93
+ end
94
+ end
95
+
96
+ class Where
97
+ def initialize(hash = {})
98
+ @hash = hash
99
+ end
100
+
101
+ def add(hash)
102
+ @hash.merge!(hash)
103
+ end
104
+
105
+ def to_s
106
+ if @hash.blank?
107
+ ""
108
+ else
109
+ "WHERE #{compute_relation}"
110
+ end
111
+ end
112
+
113
+ def compute_relation
114
+ @hash.map do |key, value|
115
+ if value.is_a? String
116
+ "#{key} = '#{value}'"
117
+ else
118
+ "#{key} = #{value}"
119
+ end
120
+ end.join(" AND ")
121
+ end
122
+ end
123
+
124
+ # An ASC or DESC modifier may appear after each field in the ORDER BY list. If no modifer appears, ASC is assumed.
125
+ # > SELECT * FROM members ORDER BY created DESC
126
+ class Order
127
+ def initialize(column, order)
128
+ @column = column
129
+ @order = order
130
+ end
131
+
132
+ def to_s
133
+ if @column.blank? || @order.blank?
134
+ ""
135
+ else
136
+ "ORDER BY #{@column} #{@desc}"
137
+ end
138
+ end
139
+ end
140
+
141
+ # the ITEMS clause can specify an alternative number of records to return per page.
142
+ # > SELECT * FROM members ITEMS 25
143
+ class Items
144
+ def initialize(count)
145
+ @count = count
146
+ end
147
+
148
+ def to_s
149
+ if @count.blank?
150
+ ""
151
+ else
152
+ "ITEMS #{@count}"
153
+ end
154
+ end
155
+ end
156
+
157
+ # By default the first page is returned. The PAGE clause allows additional pages to be returned.
158
+ # > SELECT * FROM members PAGE 5
159
+ class Page
160
+ def initialize(page)
161
+ @page = page
162
+ end
163
+
164
+ def to_s
165
+ if @page.blank?
166
+ ""
167
+ else
168
+ "PAGE #{@page}"
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end