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
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mashery::Member do
4
+ let(:url) { Mashery.rpc.url }
5
+
6
+ let(:items) {
7
+ [{"name" => "Name"}] * 10
8
+ }
9
+
10
+ let(:params) {
11
+ {
12
+ 'method' => "object.query",
13
+ 'params' => [query],
14
+ 'id' => 1
15
+ }
16
+ }
17
+
18
+ let(:headers) {
19
+ {
20
+ "Content-Type" => "application/json",
21
+ "Accept" => "text/plain",
22
+ "Content-Length" => params.size
23
+ }
24
+ }
25
+
26
+ let(:json) {
27
+ {
28
+ "result" => {
29
+ "items" => items
30
+ }
31
+ }.to_json
32
+ }
33
+
34
+
35
+ context "with standard query" do
36
+ let(:query) {
37
+ "SELECT * FROM members ITEMS 100"
38
+ }
39
+
40
+ it "should grab all the members" do
41
+ ::RestClient.should_receive(:post).with(url, params.to_json, headers).and_return(json)
42
+ objects = Mashery::Member.all
43
+ objects.length.should == 10
44
+ end
45
+ end
46
+
47
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mashery::QueryBuilder do
4
+ it "should build a simple query" do
5
+ builder = Mashery::QueryBuilder.new
6
+ builder.from("members").to_s.should == "SELECT * FROM members"
7
+ end
8
+
9
+ it "should build a query with pagination" do
10
+ builder = Mashery::QueryBuilder.new
11
+ builder.from("members").page(25).items(100).to_s.should == "SELECT * FROM members PAGE 25 ITEMS 100"
12
+ end
13
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mashery::RestClient do
4
+ let(:service_key) do
5
+ "12345"
6
+ end
7
+
8
+ let(:url) do
9
+ Mashery::RestClient::Query.new(query_params).url
10
+ end
11
+
12
+ let(:query_params) do
13
+ {service_id: service_key}.merge(options)
14
+ end
15
+
16
+
17
+ context "reasonable date range" do
18
+ let(:options) do
19
+ {
20
+ start_date: 1.day.ago,
21
+ end_date: 0.days.ago,
22
+ resource: "developer_activity"
23
+ }
24
+ end
25
+
26
+ it "should request the service data, given a service key" do
27
+ ::RestClient.should_receive(:get).with(url).and_return("whatever")
28
+ Mashery.activity("developer_activity", service_key, options).should == "whatever"
29
+ end
30
+ end
31
+
32
+ context "invalid date range" do
33
+ let(:options) do
34
+ {
35
+ start_date: 8.day.ago,
36
+ end_date: 0.days.ago,
37
+ resource: "developer_activity"
38
+ }
39
+ end
40
+
41
+ it "should raise an InvalidDateRange error" do
42
+ expect do
43
+ Mashery.activity("developer_activity", service_key, options)
44
+ end.to raise_error(Mashery::InvalidDateRange)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mashery::RpcClient do
4
+ let(:query) {
5
+ "SELECT * FROM whatevers"
6
+ }
7
+
8
+ let(:params) {
9
+ {
10
+ 'method' => "object.query",
11
+ 'params' => [query],
12
+ 'id' => 1
13
+ }
14
+ }
15
+
16
+ let(:headers) {
17
+ {
18
+ "Content-Type" => "application/json",
19
+ "Accept" => "text/plain",
20
+ "Content-Length" => params.size
21
+ }
22
+ }
23
+
24
+ it "should post to RpcClient with the proper arguments" do
25
+ ::RestClient.should_receive(:post).with(Mashery.rpc.url, params.to_json, headers).and_return({hello: 'world'}.to_json)
26
+ Mashery.rpc.query(query)
27
+ end
28
+ end
@@ -0,0 +1,101 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mashery::Service do
4
+ let(:url) { Mashery.rpc.url }
5
+
6
+ let(:items) {
7
+ [{"name" => "Name"}] * 10
8
+ }
9
+
10
+ let(:params) {
11
+ {
12
+ 'method' => "object.query",
13
+ 'params' => [query],
14
+ 'id' => 1
15
+ }
16
+ }
17
+
18
+ let(:headers) {
19
+ {
20
+ "Content-Type" => "application/json",
21
+ "Accept" => "text/plain",
22
+ "Content-Length" => params.size
23
+ }
24
+ }
25
+
26
+ let(:json) {
27
+ {
28
+ "result" => {
29
+ "items" => items
30
+ }
31
+ }.to_json
32
+ }
33
+
34
+ context "with standard query" do
35
+ let(:query) { "SELECT * FROM services ITEMS 100" }
36
+
37
+ it "should grab all the services" do
38
+ ::RestClient.should_receive(:post).with(url, params.to_json, headers).and_return(json)
39
+ objects = Mashery::Service.all
40
+ objects.length.should == 10
41
+ end
42
+ end
43
+
44
+ context "with pagination query" do
45
+ let(:query) { "SELECT * FROM services PAGE 3 ITEMS 100"}
46
+
47
+ it "should grab the 3rd page of services" do
48
+ ::RestClient.should_receive(:post).with(url, params.to_json, headers).and_return(json)
49
+ objects = Mashery::Service.page(3).all
50
+ objects.length.should == 10
51
+ end
52
+ end
53
+
54
+ context "with auto-pagination via find_each" do
55
+ let(:total_pages) { 5 }
56
+
57
+ def query(page)
58
+ if page == 1
59
+ "SELECT * FROM services ITEMS 100"
60
+ else
61
+ "SELECT * FROM services PAGE #{page} ITEMS 100"
62
+ end
63
+ end
64
+
65
+ def params(page)
66
+ {
67
+ 'method' => "object.query",
68
+ 'params' => [query(page)],
69
+ 'id' => 1
70
+ }
71
+ end
72
+
73
+ def json(page)
74
+ {
75
+ "result" => {
76
+ "total_pages" => total_pages,
77
+ "current_page" => page,
78
+ "items" => items
79
+ }
80
+ }.to_json
81
+ end
82
+
83
+ def headers(page)
84
+ {
85
+ "Content-Type" => "application/json",
86
+ "Accept" => "text/plain",
87
+ "Content-Length" => params(page).size
88
+ }
89
+ end
90
+
91
+ it "should invoke a new query for each page" do
92
+ (1..total_pages).each do |n|
93
+ ::RestClient.should_receive(:post).with(url, params(n).to_json, headers(n)).and_return(json(n))
94
+ end
95
+
96
+ Mashery::Service.find_each do |entry|
97
+ entry.should be_a(Mashery::Service)
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mashery do
4
+ # Test configuration?
5
+ end
@@ -0,0 +1,50 @@
1
+ require 'bundler'
2
+ require 'simplecov'
3
+
4
+ SimpleCov.start
5
+
6
+ $LOAD_PATH.unshift File.expand_path("./lib")
7
+ require 'mashery'
8
+
9
+ Bundler.require(:test)
10
+
11
+ require 'coveralls'
12
+ Coveralls.wear!
13
+
14
+ RSpec.configure do |config|
15
+ config.treat_symbols_as_metadata_keys_with_true_values = true
16
+ config.run_all_when_everything_filtered = true
17
+ config.filter_run :focus
18
+
19
+ # Run specs in random order to surface order dependencies. If you find an
20
+ # order dependency and want to debug it, you can fix the order by providing
21
+ # the seed, which is printed after each run.
22
+ # --seed 1234
23
+ config.order = 'random'
24
+
25
+ config.before do
26
+ Timecop.freeze Time.now
27
+ end
28
+
29
+ config.before do
30
+ config = double("config")
31
+
32
+ key = "regular_key"
33
+ secret = "super_long_secret"
34
+ signature = Digest::MD5.hexdigest(key + secret + Time.now.to_f.to_i.to_s)
35
+
36
+ config.stub({
37
+ site_id: "987",
38
+ key: key,
39
+ secret: secret,
40
+ signature: signature,
41
+ host: "masheri.example.com",
42
+ })
43
+
44
+ Mashery.config = config
45
+ end
46
+
47
+ config.after do
48
+ Timecop.return
49
+ end
50
+ end
@@ -0,0 +1,200 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.setup
4
+
5
+ # XXX: only do this when the task has not been installed
6
+ $: << 'lib'
7
+
8
+ require 'mashery'
9
+
10
+ module Mashery
11
+ class CLI < Thor
12
+ namespace :mashery
13
+
14
+ desc "echo VALUE", "Echo the provided value (tests connectivity and authentication)"
15
+ def echo(value)
16
+ run { ok(::Mashery.client.echo(value)) }
17
+ end
18
+
19
+ protected
20
+ def run(&block)
21
+ site_id = ENV['MASHERY_SITE_ID'] or
22
+ raise Exception, "Please set the MASHERY_SITE_ID environment variable."
23
+ key = ENV['MASHERY_API_KEY'] or
24
+ raise Exception, "Please set the MASHERY_API_KEY environment variable."
25
+ secret = ENV['MASHERY_SHARED_SECRET'] or
26
+ raise Exception, "Please set the MASHERY_SHARED_SECRET environment variable."
27
+ ::Mashery.test_mode = ENV['MASHERY_PRODUCTION_MODE'].blank?
28
+ ::Mashery.logger.level = Logger::DEBUG
29
+ ::Mashery.client = ::Mashery::Client.new(site_id, key, secret)
30
+ begin
31
+ yield
32
+ rescue ::Mashery::HttpException => e
33
+ error("HTTP error: #{e.message}")
34
+ rescue ::Mashery::JsonRpcException => e
35
+ error(e.message)
36
+ rescue ::Mashery::ValidationException => e
37
+ e.errors.each {|err| warn("#{err['field']}: #{err['message']}")}
38
+ error("Unable to execute method due to validation errors")
39
+ end
40
+ end
41
+
42
+ def warn(msg)
43
+ say_status :WARN, msg, :yellow
44
+ end
45
+
46
+ def ok(msg)
47
+ say_status :OK, msg
48
+ end
49
+
50
+ def error(msg)
51
+ say_status :ERROR, msg, :red
52
+ end
53
+
54
+ def debug(msg)
55
+ say_status :DEBUG, msg, :cyan
56
+ end
57
+ end
58
+
59
+ class MemberCLI < CLI
60
+ namespace 'mashery:member'
61
+
62
+ desc "create USERNAME DISPLAY_NAME EMAIL [--fields ...]", "Create a member"
63
+ method_option :fields, :type => :hash
64
+ def create(username, display_name, email)
65
+ run do
66
+ begin
67
+ member = ::Mashery::Member.create(username, display_name, email, options[:fields])
68
+ ok("Member #{member.username} created")
69
+ rescue ::Mashery::DuplicateObjectException
70
+ error("The username #{username} has already been claimed")
71
+ end
72
+ end
73
+ end
74
+
75
+ desc "fetch USERNAME", "Fetch a member"
76
+ def fetch(username)
77
+ run do
78
+ member = ::Mashery::Member.fetch(username)
79
+ if member
80
+ ok("Member #{username} found")
81
+ say(member.to_yaml)
82
+ else
83
+ warn("Member #{username} not found")
84
+ end
85
+ end
86
+ end
87
+
88
+ desc "addrole USERNAME ROLE_ID", "Assign a role to a member"
89
+ def addrole(username, role_id)
90
+ run do
91
+ member = ::Mashery::Member.fetch(username)
92
+ if member
93
+ role = ::Mashery::Role.fetch(role_id.to_i)
94
+ if role
95
+ member.add_role(role)
96
+ ok("Role #{role.name} assigned to member #{username}")
97
+ else
98
+ warn("Role #{role_id} not found")
99
+ end
100
+ else
101
+ warn("Member #{username} not found")
102
+ end
103
+ end
104
+ end
105
+
106
+ desc "rmrole USERNAME ROLE_ID", "Revoke a role from a member"
107
+ def rmrole(username, role_id)
108
+ run do
109
+ member = ::Mashery::Member.fetch(username)
110
+ if member
111
+ role = ::Mashery::Role.fetch(role_id.to_i)
112
+ if role
113
+ member.remove_role(role)
114
+ ok("Role #{role.name} revoked from member #{username}")
115
+ else
116
+ warn("Role #{role_id} not found")
117
+ end
118
+ else
119
+ warn("Member #{username} not found")
120
+ end
121
+ end
122
+ end
123
+
124
+ desc "delete USERNAME", "Delete a member"
125
+ def delete(username)
126
+ run do
127
+ ::Mashery::Member.delete(username)
128
+ ok("Member #{username} deleted")
129
+ end
130
+ end
131
+ end
132
+
133
+ class KeyCLI < CLI
134
+ namespace 'mashery:key'
135
+
136
+ desc "create SERVICE_KEY USERNAME [--fields ...]", "Create a key"
137
+ method_option :fields, :type => :hash
138
+ def create(service_key, username)
139
+ run do
140
+ key = ::Mashery::Key.create(service_key, username, options[:fields])
141
+ ok("Key #{key.id} created for member #{username} and service #{service_key}")
142
+ end
143
+ end
144
+
145
+ desc "fetch ID", "Fetch a key"
146
+ def fetch(id)
147
+ run do
148
+ key = ::Mashery::Key.fetch(id.to_i)
149
+ if key
150
+ ok("Key #{id} found")
151
+ say(key.to_yaml)
152
+ else
153
+ warn("Key #{id} not found")
154
+ end
155
+ end
156
+ end
157
+
158
+ desc "delete ID", "Delete a key"
159
+ def delete(id)
160
+ run do
161
+ ::Mashery::Key.delete(id.to_i)
162
+ ok("Key #{id} deleted")
163
+ end
164
+ end
165
+ end
166
+
167
+ class RoleCLI < CLI
168
+ namespace 'mashery:role'
169
+
170
+ desc "create NAME [--fields ...]", "Create a role"
171
+ method_option :fields, :type => :hash
172
+ def create(name)
173
+ run do
174
+ role = ::Mashery::Role.create(name, options[:fields])
175
+ ok("Role #{role.id} created with name #{name}")
176
+ end
177
+ end
178
+
179
+ desc "fetch ID", "Fetch a role"
180
+ def fetch(id)
181
+ run do
182
+ role = ::Mashery::Role.fetch(id.to_i)
183
+ if role
184
+ ok("Role #{id} found")
185
+ say(role.to_yaml)
186
+ else
187
+ warn("Role #{id} not found")
188
+ end
189
+ end
190
+ end
191
+
192
+ desc "delete ID", "Delete a role"
193
+ def delete(id)
194
+ run do
195
+ ::Mashery::Role.delete(id.to_i)
196
+ ok("Role #{id} deleted")
197
+ end
198
+ end
199
+ end
200
+ end