leadlight 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/Gemfile +9 -0
  2. data/Gemfile.lock +79 -0
  3. data/Guardfile +19 -0
  4. data/Rakefile +133 -0
  5. data/leadlight.gemspec +125 -0
  6. data/lib/leadlight.rb +92 -0
  7. data/lib/leadlight/blank.rb +15 -0
  8. data/lib/leadlight/codec.rb +63 -0
  9. data/lib/leadlight/enumerable_representation.rb +24 -0
  10. data/lib/leadlight/errors.rb +14 -0
  11. data/lib/leadlight/hyperlinkable.rb +126 -0
  12. data/lib/leadlight/link.rb +35 -0
  13. data/lib/leadlight/link_template.rb +47 -0
  14. data/lib/leadlight/representation.rb +30 -0
  15. data/lib/leadlight/request.rb +91 -0
  16. data/lib/leadlight/service.rb +73 -0
  17. data/lib/leadlight/service_middleware.rb +50 -0
  18. data/lib/leadlight/tint.rb +26 -0
  19. data/lib/leadlight/tint_helper.rb +67 -0
  20. data/lib/leadlight/type.rb +71 -0
  21. data/spec/cassettes/Leadlight/authorized_GitHub_example/_user/has_the_expected_content.yml +75 -0
  22. data/spec/cassettes/Leadlight/authorized_GitHub_example/_user/indicates_the_expected_oath_scopes.yml +75 -0
  23. data/spec/cassettes/Leadlight/authorized_GitHub_example/adding_and_removing_team_members.yml +384 -0
  24. data/spec/cassettes/Leadlight/authorized_GitHub_example/adding_and_removing_team_members/.yml +309 -0
  25. data/spec/cassettes/Leadlight/authorized_GitHub_example/test_team/.yml +159 -0
  26. data/spec/cassettes/Leadlight/basic_GitHub_example/_root/.yml +32 -0
  27. data/spec/cassettes/Leadlight/basic_GitHub_example/_root/__location__/.yml +32 -0
  28. data/spec/cassettes/Leadlight/basic_GitHub_example/_root/should_be_a_204_no_content.yml +32 -0
  29. data/spec/cassettes/Leadlight/tinted_GitHub_example/_root/.yml +32 -0
  30. data/spec/cassettes/Leadlight/tinted_GitHub_example/_root/__location__/.yml +32 -0
  31. data/spec/cassettes/Leadlight/tinted_GitHub_example/_root/should_be_a_204_no_content.yml +32 -0
  32. data/spec/cassettes/Leadlight/tinted_GitHub_example/_user/has_the_expected_content.yml +65 -0
  33. data/spec/cassettes/Leadlight/tinted_GitHub_example/user_followers/.yml +100 -0
  34. data/spec/cassettes/Leadlight/tinted_GitHub_example/user_followers/should_be_able_to_follow_next_link.yml +135 -0
  35. data/spec/cassettes/Leadlight/tinted_GitHub_example/user_followers/should_be_enumerable.yml +275 -0
  36. data/spec/cassettes/Leadlight/tinted_GitHub_example/user_followers/should_be_enumerable_over_page_boundaries.yml +170 -0
  37. data/spec/cassettes/Leadlight/tinted_GitHub_example/user_followers/should_have_next_and_last_links.yml +100 -0
  38. data/spec/cassettes/Leadlight/tinted_GitHub_example/user_link/exists.yml +32 -0
  39. data/spec/cassettes/Leadlight/tinted_GitHub_example/user_link/links_to_the_expected_URL.yml +32 -0
  40. data/spec/leadlight/codec_spec.rb +93 -0
  41. data/spec/leadlight/hyperlinkable_spec.rb +136 -0
  42. data/spec/leadlight/link_spec.rb +53 -0
  43. data/spec/leadlight/link_template_spec.rb +45 -0
  44. data/spec/leadlight/representation_spec.rb +62 -0
  45. data/spec/leadlight/request_spec.rb +236 -0
  46. data/spec/leadlight/service_middleware_spec.rb +81 -0
  47. data/spec/leadlight/service_spec.rb +127 -0
  48. data/spec/leadlight/tint_helper_spec.rb +132 -0
  49. data/spec/leadlight/type_spec.rb +137 -0
  50. data/spec/leadlight_spec.rb +237 -0
  51. data/spec/spec_helper_lite.rb +6 -0
  52. data/spec/support/credentials.rb +16 -0
  53. data/spec/support/vcr.rb +18 -0
  54. metadata +229 -0
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ # I fear there's no reasonable way to do conditional dependencies like this in
6
+ # a gemspec.
7
+ gem 'rb-inotify' if RUBY_PLATFORM =~ /linux/i
8
+ gem 'libnotify' if RUBY_PLATFORM =~ /linux/i
9
+
data/Gemfile.lock ADDED
@@ -0,0 +1,79 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ leadlight (0.0.1)
5
+ faraday
6
+ fattr
7
+ hookr
8
+ link_header
9
+ mime-types
10
+ multi_json
11
+
12
+ GEM
13
+ remote: http://rubygems.org/
14
+ specs:
15
+ addressable (2.2.6)
16
+ archive-tar-minitar (0.5.2)
17
+ columnize (0.3.6)
18
+ diff-lcs (1.1.3)
19
+ fail-fast (1.0.0)
20
+ faraday (0.7.5)
21
+ addressable (~> 2.2.6)
22
+ multipart-post (~> 1.1.3)
23
+ rack (< 2, >= 1.1.0)
24
+ fattr (2.2.0)
25
+ ffi (1.0.11)
26
+ guard (0.10.0)
27
+ ffi (>= 0.5.0)
28
+ thor (~> 0.14.6)
29
+ guard-bundler (0.1.3)
30
+ bundler (>= 1.0.0)
31
+ guard (>= 0.2.2)
32
+ guard-rspec (0.6.0)
33
+ guard (>= 0.10.0)
34
+ hookr (1.1.1)
35
+ fail-fast (= 1.0.0)
36
+ libnotify (0.7.1)
37
+ linecache19 (0.5.12)
38
+ ruby_core_source (>= 0.1.4)
39
+ link_header (0.0.5)
40
+ mime-types (1.17.2)
41
+ multi_json (1.0.4)
42
+ multipart-post (1.1.4)
43
+ rack (1.4.0)
44
+ rb-inotify (0.8.8)
45
+ ffi (>= 0.5.0)
46
+ rspec (2.7.0)
47
+ rspec-core (~> 2.7.0)
48
+ rspec-expectations (~> 2.7.0)
49
+ rspec-mocks (~> 2.7.0)
50
+ rspec-core (2.7.1)
51
+ rspec-expectations (2.7.0)
52
+ diff-lcs (~> 1.1.2)
53
+ rspec-mocks (2.7.0)
54
+ ruby-debug-base19 (0.11.25)
55
+ columnize (>= 0.3.1)
56
+ linecache19 (>= 0.5.11)
57
+ ruby_core_source (>= 0.1.4)
58
+ ruby-debug19 (0.11.6)
59
+ columnize (>= 0.3.1)
60
+ linecache19 (>= 0.5.11)
61
+ ruby-debug-base19 (>= 0.11.19)
62
+ ruby_core_source (0.1.5)
63
+ archive-tar-minitar (>= 0.5.2)
64
+ thor (0.14.6)
65
+ vcr (2.0.0.rc1)
66
+
67
+ PLATFORMS
68
+ ruby
69
+
70
+ DEPENDENCIES
71
+ guard
72
+ guard-bundler
73
+ guard-rspec
74
+ leadlight!
75
+ libnotify
76
+ rb-inotify
77
+ rspec
78
+ ruby-debug19
79
+ vcr (~> 2.0.0.rc1)
data/Guardfile ADDED
@@ -0,0 +1,19 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ # Rails example
10
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
11
+ watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
12
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
13
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
14
+ watch('config/routes.rb') { "spec/routing" }
15
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
16
+ # Capybara request specs
17
+ watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
18
+ end
19
+
data/Rakefile ADDED
@@ -0,0 +1,133 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'date'
4
+
5
+ #############################################################################
6
+ #
7
+ # Helper functions
8
+ #
9
+ #############################################################################
10
+
11
+ def name
12
+ @name ||= Dir['*.gemspec'].first.split('.').first
13
+ end
14
+
15
+ def version
16
+ line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/]
17
+ line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
18
+ end
19
+
20
+ def date
21
+ Date.today.to_s
22
+ end
23
+
24
+ def rubyforge_project
25
+ name
26
+ end
27
+
28
+ def gemspec_file
29
+ "#{name}.gemspec"
30
+ end
31
+
32
+ def gem_file
33
+ "#{name}-#{version}.gem"
34
+ end
35
+
36
+ def replace_header(head, header_name)
37
+ head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
38
+ end
39
+
40
+ #############################################################################
41
+ #
42
+ # Standard tasks
43
+ #
44
+ #############################################################################
45
+
46
+ require 'rspec'
47
+ require 'rspec/core/rake_task'
48
+
49
+ desc "Run all specs"
50
+ task RSpec::Core::RakeTask.new('spec')
51
+
52
+ task :default => "spec"
53
+
54
+ desc "Open an irb session preloaded with this library"
55
+ task :console do
56
+ sh "irb -rubygems -r ./lib/#{name}.rb"
57
+ end
58
+
59
+ #############################################################################
60
+ #
61
+ # Custom tasks (add your own tasks here)
62
+ #
63
+ #############################################################################
64
+
65
+
66
+
67
+ #############################################################################
68
+ #
69
+ # Packaging tasks
70
+ #
71
+ #############################################################################
72
+
73
+ desc "Create tag v#{version} and build and push #{gem_file} to Rubygems"
74
+ task :release => :build do
75
+ unless `git branch` =~ /^\* master$/
76
+ puts "You must be on the master branch to release!"
77
+ exit!
78
+ end
79
+ sh "git commit --allow-empty -a -m 'Release #{version}'"
80
+ sh "git tag v#{version}"
81
+ sh "git push origin master"
82
+ sh "git push origin v#{version}"
83
+ sh "gem push pkg/#{name}-#{version}.gem"
84
+ end
85
+
86
+ desc "Build #{gem_file} into the pkg directory"
87
+ task :build => :gemspec do
88
+ sh "mkdir -p pkg"
89
+ sh "gem build #{gemspec_file}"
90
+ sh "mv #{gem_file} pkg"
91
+ end
92
+
93
+ desc "Generate #{gemspec_file}"
94
+ task :gemspec => :validate do
95
+ # read spec file and split out manifest section
96
+ spec = File.read(gemspec_file)
97
+ head, manifest, tail = spec.split(" # = MANIFEST =\n")
98
+
99
+ # replace name version and date
100
+ replace_header(head, :name)
101
+ replace_header(head, :version)
102
+ replace_header(head, :date)
103
+ #comment this out if your rubyforge_project has a different name
104
+ replace_header(head, :rubyforge_project)
105
+
106
+ # determine file list from git ls-files
107
+ files = `git ls-files`.
108
+ split("\n").
109
+ sort.
110
+ reject { |file| file =~ /^\./ }.
111
+ reject { |file| file =~ /^(rdoc|pkg)/ }.
112
+ map { |file| " #{file}" }.
113
+ join("\n")
114
+
115
+ # piece file back together and write
116
+ manifest = " s.files = %w[\n#{files}\n ]\n"
117
+ spec = [head, manifest, tail].join(" # = MANIFEST =\n")
118
+ File.open(gemspec_file, 'w') { |io| io.write(spec) }
119
+ puts "Updated #{gemspec_file}"
120
+ end
121
+
122
+ desc "Validate #{gemspec_file}"
123
+ task :validate do
124
+ libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
125
+ unless libfiles.empty?
126
+ puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir."
127
+ exit!
128
+ end
129
+ unless Dir['VERSION*'].empty?
130
+ puts "A `VERSION` file at root level violates Gem best practices."
131
+ exit!
132
+ end
133
+ end
data/leadlight.gemspec ADDED
@@ -0,0 +1,125 @@
1
+ ## This is the rakegem gemspec template. Make sure you read and understand
2
+ ## all of the comments. Some sections require modification, and others can
3
+ ## be deleted if you don't need them. Once you understand the contents of
4
+ ## this file, feel free to delete any comments that begin with two hash marks.
5
+ ## You can find comprehensive Gem::Specification documentation, at
6
+ ## http://docs.rubygems.org/read/chapter/20
7
+ Gem::Specification.new do |s|
8
+ s.specification_version = 2 if s.respond_to? :specification_version=
9
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
10
+ s.rubygems_version = '1.3.5'
11
+
12
+ ## Leave these as is they will be modified for you by the rake gemspec task.
13
+ ## If your rubyforge_project name is different, then edit it and comment out
14
+ ## the sub! line in the Rakefile
15
+ s.name = 'leadlight'
16
+ s.version = '0.0.2'
17
+ s.date = '2012-01-09'
18
+ s.rubyforge_project = 'leadlight'
19
+
20
+ ## Make sure your summary is short. The description may be as long
21
+ ## as you like.
22
+ s.summary = "Short description used in Gem listings."
23
+ s.description = "Long description. Maybe copied from the README."
24
+
25
+ ## List the primary authors. If there are a bunch of authors, it's probably
26
+ ## better to set the email to an email list or something. If you don't have
27
+ ## a custom homepage, consider using your GitHub URL or the like.
28
+ s.authors = ["Avdi Grimm"]
29
+ s.email = 'avdi@avdi.org'
30
+ s.homepage = 'https://github.com/avdi/leadlight'
31
+
32
+ ## This gets added to the $LOAD_PATH so that 'lib/NAME.rb' can be required as
33
+ ## require 'NAME.rb' or'/lib/NAME/file.rb' can be as require 'NAME/file.rb'
34
+ s.require_paths = %w[lib]
35
+
36
+ ## Specify any RDoc options here. You'll want to add your README and
37
+ ## LICENSE files to the extra_rdoc_files list.
38
+ ## s.rdoc_options = ["--charset=UTF-8"]
39
+ ## s.extra_rdoc_files = %w[README LICENSE]
40
+
41
+ ## List your runtime dependencies here. Runtime dependencies are those
42
+ ## that are needed for an end user to actually USE your code.
43
+ ## s.add_dependency('DEPNAME', [">= 1.1.0", "< 2.0.0"])
44
+ s.add_dependency 'faraday'
45
+ s.add_dependency 'fattr'
46
+ s.add_dependency 'link_header'
47
+ s.add_dependency 'multi_json'
48
+ s.add_dependency 'mime-types'
49
+ s.add_dependency 'hookr'
50
+
51
+ ## List your development dependencies here. Development dependencies are
52
+ ## those that are only needed during development
53
+ ## s.add_development_dependency('DEVDEPNAME', [">= 1.1.0", "< 2.0.0"])
54
+ s.add_development_dependency 'rspec'
55
+ s.add_development_dependency 'vcr', '~> 2.0.0.rc1'
56
+ s.add_development_dependency 'guard'
57
+ s.add_development_dependency 'guard-rspec'
58
+ s.add_development_dependency 'guard-bundler'
59
+ s.add_development_dependency 'ruby-debug19'
60
+
61
+ ## Leave this section as-is. It will be automatically generated from the
62
+ ## contents of your Git repository via the gemspec task. DO NOT REMOVE
63
+ ## THE MANIFEST COMMENTS, they are used as delimiters by the task.
64
+ # = MANIFEST =
65
+ s.files = %w[
66
+ Gemfile
67
+ Gemfile.lock
68
+ Guardfile
69
+ Rakefile
70
+ leadlight.gemspec
71
+ lib/leadlight.rb
72
+ lib/leadlight/blank.rb
73
+ lib/leadlight/codec.rb
74
+ lib/leadlight/enumerable_representation.rb
75
+ lib/leadlight/errors.rb
76
+ lib/leadlight/hyperlinkable.rb
77
+ lib/leadlight/link.rb
78
+ lib/leadlight/link_template.rb
79
+ lib/leadlight/representation.rb
80
+ lib/leadlight/request.rb
81
+ lib/leadlight/service.rb
82
+ lib/leadlight/service_middleware.rb
83
+ lib/leadlight/tint.rb
84
+ lib/leadlight/tint_helper.rb
85
+ lib/leadlight/type.rb
86
+ spec/cassettes/Leadlight/authorized_GitHub_example/_user/has_the_expected_content.yml
87
+ spec/cassettes/Leadlight/authorized_GitHub_example/_user/indicates_the_expected_oath_scopes.yml
88
+ spec/cassettes/Leadlight/authorized_GitHub_example/adding_and_removing_team_members.yml
89
+ spec/cassettes/Leadlight/authorized_GitHub_example/adding_and_removing_team_members/.yml
90
+ spec/cassettes/Leadlight/authorized_GitHub_example/test_team/.yml
91
+ spec/cassettes/Leadlight/basic_GitHub_example/_root/.yml
92
+ spec/cassettes/Leadlight/basic_GitHub_example/_root/__location__/.yml
93
+ spec/cassettes/Leadlight/basic_GitHub_example/_root/should_be_a_204_no_content.yml
94
+ spec/cassettes/Leadlight/tinted_GitHub_example/_root/.yml
95
+ spec/cassettes/Leadlight/tinted_GitHub_example/_root/__location__/.yml
96
+ spec/cassettes/Leadlight/tinted_GitHub_example/_root/should_be_a_204_no_content.yml
97
+ spec/cassettes/Leadlight/tinted_GitHub_example/_user/has_the_expected_content.yml
98
+ spec/cassettes/Leadlight/tinted_GitHub_example/user_followers/.yml
99
+ spec/cassettes/Leadlight/tinted_GitHub_example/user_followers/should_be_able_to_follow_next_link.yml
100
+ spec/cassettes/Leadlight/tinted_GitHub_example/user_followers/should_be_enumerable.yml
101
+ spec/cassettes/Leadlight/tinted_GitHub_example/user_followers/should_be_enumerable_over_page_boundaries.yml
102
+ spec/cassettes/Leadlight/tinted_GitHub_example/user_followers/should_have_next_and_last_links.yml
103
+ spec/cassettes/Leadlight/tinted_GitHub_example/user_link/exists.yml
104
+ spec/cassettes/Leadlight/tinted_GitHub_example/user_link/links_to_the_expected_URL.yml
105
+ spec/leadlight/codec_spec.rb
106
+ spec/leadlight/hyperlinkable_spec.rb
107
+ spec/leadlight/link_spec.rb
108
+ spec/leadlight/link_template_spec.rb
109
+ spec/leadlight/representation_spec.rb
110
+ spec/leadlight/request_spec.rb
111
+ spec/leadlight/service_middleware_spec.rb
112
+ spec/leadlight/service_spec.rb
113
+ spec/leadlight/tint_helper_spec.rb
114
+ spec/leadlight/type_spec.rb
115
+ spec/leadlight_spec.rb
116
+ spec/spec_helper_lite.rb
117
+ spec/support/credentials.rb
118
+ spec/support/vcr.rb
119
+ ]
120
+ # = MANIFEST =
121
+
122
+ ## Test files will be grabbed from the file list. Make sure the path glob
123
+ ## matches what you actually use.
124
+ s.test_files = s.files.select { |path| path =~ /^test\/test_.*\.rb/ }
125
+ end
data/lib/leadlight.rb ADDED
@@ -0,0 +1,92 @@
1
+ require 'faraday'
2
+ require 'fattr'
3
+ require 'logger'
4
+ require 'leadlight/errors'
5
+ require 'leadlight/link'
6
+ require 'leadlight/hyperlinkable'
7
+ require 'leadlight/service_middleware'
8
+ require 'leadlight/representation'
9
+ require 'leadlight/tint'
10
+ require 'leadlight/type'
11
+ require 'leadlight/service'
12
+ require 'leadlight/enumerable_representation'
13
+
14
+
15
+ module Leadlight
16
+
17
+ VERSION = '0.0.2'
18
+
19
+ def self.build_service(target, &block)
20
+ target.module_eval do
21
+ extend ServiceClassMethods
22
+ include Service
23
+ end
24
+ target.module_eval(&block)
25
+ end
26
+
27
+ def self.build_connection_common(&common_connection_stack)
28
+ @common_connection_stack = common_connection_stack
29
+ end
30
+
31
+ def self.common_connection_stack
32
+ @common_connection_stack ||= ->(builder) {
33
+ builder.adapter :net_http
34
+ }
35
+ end
36
+
37
+ module ServiceClassMethods
38
+ fattr(:tints) { default_tints }
39
+ fattr(:types) { [] }
40
+
41
+ def url(new_url=:none)
42
+ if new_url == :none
43
+ @url ||= Addressable::URI.parse('http://example.com')
44
+ else
45
+ @url = Addressable::URI.parse(new_url)
46
+ end
47
+ end
48
+
49
+ def session(options={})
50
+ sessions[options]
51
+ end
52
+
53
+ def sessions
54
+ @sessions ||= Hash.new{|h,k|
55
+ h[k] = new(k)
56
+ }
57
+ end
58
+
59
+ def connection_stack
60
+ @connection_stack ||= ->(builder){}
61
+ end
62
+
63
+ def default_tints
64
+ [
65
+ EnumerableRepresentation::Tint
66
+ ]
67
+ end
68
+
69
+ private
70
+
71
+ def tint(name, &block)
72
+ self.tints << Tint.new(name, &block)
73
+ end
74
+
75
+ def type(name, &block)
76
+ self.types << Type.new(name, self, &block)
77
+ end
78
+
79
+ def type_for_name(name)
80
+ raise_on_missing = -> do
81
+ raise KeyError, "Type not found: #{name}"
82
+ end
83
+ types.detect(raise_on_missing){|type| type.name.to_s == name.to_s}
84
+ end
85
+
86
+ def build_connection(&block)
87
+ @connection_stack = block
88
+ end
89
+
90
+ end
91
+
92
+ end