served 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 29a2b56443a1a80b781afd1a6748db0d0c36164b
4
+ data.tar.gz: 9d12321a5ed7b46bc639dcf8791e2f236beb26a3
5
+ SHA512:
6
+ metadata.gz: e51558cc1fe9f0b87b7c0141f2a107c3e823f3a1838d8177518ad6433232f5967781c16ba5c9048a0f160ad07a9167b4817f1a79d0aabd4fbfd15581762cc910
7
+ data.tar.gz: 748a36574dfdcbb27f39a3cb948e2fd237562945254367265b1509032cd8690f4d7f4d8e8eff3ac9d6023b8eac7f0b5d76578b26b59e61f5b9db0c90561c3978
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.iml
11
+ .idea/**
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.2
4
+ before_install: gem install bundler -v 1.10.5
@@ -0,0 +1,13 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4
+
5
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
6
+
7
+ Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8
+
9
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10
+
11
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12
+
13
+ This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in served.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Jarod Reid
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # Served
2
+ [![Build Status](https://travis-ci.org/fugufish/served.svg)](https://travis-ci.org/fugufish/served)
3
+
4
+ Served is a gem in the vein of [ActiveResource](https://github.com/rails/activeresource) designed to facilitate
5
+ communication between distributed Rails services.
6
+
7
+ # Installation
8
+
9
+ Add the following to your Gemfile:
10
+
11
+ ```gem 'served'```
12
+
13
+ # Usage
14
+
15
+ ```ruby
16
+ class SomeService::SomeResource < Served::Resource::Base
17
+
18
+ attribute :name
19
+ attribute :date
20
+ attribute :phone_number
21
+
22
+ end
23
+ ```
24
+
25
+ # Configuration
26
+
27
+ Served is configured using ```Served.config```.
28
+
29
+ ## Configuration Options
30
+
31
+ ### Hosts (required)
32
+
33
+ Served uses the adjacent namespace of the resource to determine the the url for that service. For example given this
34
+ configuration:
35
+
36
+ ```ruby
37
+ Served.configure do |c|
38
+ c.hosts = {
39
+ some_service: 'http://localhost:3000',
40
+ some_other_service: 'http://localhost:3001'
41
+ }
42
+ ```
43
+
44
+ and given this resource
45
+
46
+ ```ruby
47
+ class SomeService::SomeResource < Served::Resource::Base
48
+
49
+ attribute :name
50
+ attribute :date
51
+ attribute :phone_number
52
+
53
+ end
54
+ ```
55
+
56
+ ```SomeService::SomeResource``` would map back to http://localhost:3000/some_resources.
57
+
58
+ ### Timeout
59
+
60
+ Sets the request time out.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "served"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
data/lib/served.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'httparty'
2
+ require 'active_support/configurable'
3
+ require 'active_support/core_ext/string'
4
+ require 'active_support/core_ext/module'
5
+
6
+ require 'served/engine'
7
+ require 'served/version'
8
+ require 'served/http_client'
9
+ require 'served/resource'
10
+
11
+ module Served
12
+ include ActiveSupport::Configurable
13
+ configure do |config|
14
+ config.timeout = 30
15
+ end
16
+ end
@@ -0,0 +1,6 @@
1
+ if Object.const_defined?(:Rails)
2
+ module Served
3
+ class Engine < ::Rails::Engine
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,38 @@
1
+ module Served
2
+ # Provides an interface between HTTParty and the models. Most of the crap in here is self explanatory
3
+ class HTTPClient
4
+ HEADERS = { 'Content-type' => 'application/json', 'Accept' => 'application/json' }
5
+
6
+ def initialize(host)
7
+ @host = host
8
+ end
9
+
10
+ def get(endpoint, params={})
11
+ HTTParty.get("#{@host}/#{endpoint}",
12
+ query: params,
13
+ headers: HEADERS,
14
+ timeout: Served.config.timeout
15
+ )
16
+ end
17
+
18
+ def put(endpoint, body, params={})
19
+ HTTParty.put(
20
+ "#{@host}/#{endpoint}",
21
+ body: body,
22
+ query: params,
23
+ headers: HEADERS,
24
+ timeout: Served.config.timeout
25
+ )
26
+ end
27
+
28
+ def post(endpoint, body, params={})
29
+ HTTParty.post(
30
+ "#{@host}/#{endpoint}",
31
+ body: body,
32
+ query: params,
33
+ headers: HEADERS,
34
+ timeout: Served.config.timeout
35
+ )
36
+ end
37
+ end
38
+ end
@@ -0,0 +1 @@
1
+ require 'served/resource/base'
@@ -0,0 +1,157 @@
1
+ module Served
2
+ module Resource
3
+ # Service Resources should inherit directly from this class. Provides interfaces necessary for communicating with
4
+ # services based on the namespace. Classes should be namespaced under Services::ServiceName where ServiceName is the
5
+ # name of the service the resource lives on. The resource determines the host of the service based on this
6
+ # this namespace and what is in the configuration.
7
+ class Base
8
+ # raised when an attribute is passed to a resource that is not declared
9
+ class InvalidAttributeError < StandardError; end
10
+
11
+ # raised when the connection receives a response from a service that does not constitute a 200
12
+ class ServiceError < StandardError
13
+ def initialize(response)
14
+ @code = response.code
15
+ super "An error occurred making the request: #{@code}"
16
+ end
17
+ end
18
+
19
+ class << self
20
+ # declare an attribute for the resource
21
+ #
22
+ # @example
23
+ # class SomeResource
24
+ # attribute :attr1
25
+ # end
26
+ def attribute(name)
27
+ return if attributes.include?(name)
28
+ attributes << name
29
+ attr_accessor name
30
+ end
31
+
32
+ # @return [Array] declared attributes for the resources
33
+ def attributes
34
+ @attributes ||= []
35
+ end
36
+
37
+ # Looks up a resource on the service by id. For example `SomeResource.find(5)` would call `/some_resources/5`
38
+ def find(id)
39
+ instance = new(id: id)
40
+ instance.reload
41
+ end
42
+
43
+ # @return [String] the name of the resource. `SomeResource.resource_name` will return `some_resources`
44
+ def resource_name
45
+ name.split('::').last.tableize
46
+ end
47
+
48
+ # @return [String] the configured host.
49
+ # @see Services::Configuration
50
+ def host
51
+ Served.config[:hosts][parent.name.underscore.split('/')[-1]]
52
+ end
53
+
54
+ # @return [Served::HTTPClient] The connection instance to the service host. Note this is not an active
55
+ # connection but a passive one.
56
+ def client
57
+ @connection ||= Served::HTTPClient.new(host)
58
+ end
59
+
60
+ private
61
+
62
+ # Everything should allow an id attribute
63
+ def inherited(subclass)
64
+ return if subclass.attributes.include?(:id) # attribute method does this already, but rather not do a
65
+ # class_eval if not necessary
66
+ subclass.class_eval do
67
+ attribute :id
68
+ end
69
+ end
70
+ end
71
+
72
+ # Instantiates a resource with the given attributes.
73
+ #
74
+ # @raise [InvalidAttributeError] in the case that an attribute is passed that is not declared
75
+ def initialize(attributes={})
76
+ reload_with_attributes(attributes)
77
+ end
78
+
79
+ # @see Services::Resource::Base::resource_name
80
+ def resource_name
81
+ self.class.resource_name
82
+ end
83
+
84
+ # Saves the record to the service. Will call POST if the record does not have an id, otherwise will call PUT
85
+ # to update the record
86
+ def save
87
+ if id
88
+ reload_with_attributes(put[resource_name.singularize])
89
+ else
90
+ reload_with_attributes(post[resource_name.singularize])
91
+ end
92
+ true
93
+ end
94
+
95
+ alias_method :save!, :save # TODO: differentiate save! and safe much the same AR does.
96
+
97
+ # Returns a hash of attributes. If `with_values` is true, it will return only attributes whose values are not nil
98
+ #
99
+ # @param [Boolean] with_values whether or not to return all attributes or only those whose values are not nil
100
+ def attributes
101
+ Hash[self.class.attributes.collect { |name| [name, send(name)] }]
102
+ end
103
+
104
+ # Reloads the resource using attributes from the service
105
+ def reload
106
+ reload_with_attributes(get)
107
+ end
108
+
109
+ # renders the model as json
110
+ def to_json
111
+ raise InvalidPresenter, 'Presenter must respond to #to_json' unless presenter.respond_to? :to_json
112
+ presenter.to_json
113
+ end
114
+
115
+ # override this to return a presenter to be used for serialization, otherwise all attributes will be
116
+ # serialized
117
+ def presenter
118
+ { resource_name.singularize => attributes }
119
+ end
120
+
121
+ private
122
+
123
+ def get(params={})
124
+ handle_response(client.get("/#{resource_name}/#{id}.json", params))
125
+ end
126
+
127
+ def put(params={})
128
+ body = to_json
129
+ handle_response(client.put("/#{resource_name}/#{id}.json", body, params))
130
+ end
131
+
132
+ def post(params={})
133
+ body = to_json
134
+ handle_response(client.post("/#{resource_name}.json", body, params))
135
+ end
136
+
137
+ def handle_response(response)
138
+ raise ServiceError, response unless (200..299).include?(response.code)
139
+ JSON.parse(response.body)
140
+ end
141
+
142
+
143
+ def reload_with_attributes(attributes)
144
+ attributes.each { |name, value| set_attribute(name.to_sym, value) }
145
+ end
146
+
147
+ def set_attribute(name, value)
148
+ raise InvalidAttributeError, "`#{name}' is not a valid attribute" unless self.class.attributes.include?(name)
149
+ instance_variable_set("@#{name}", value)
150
+ end
151
+
152
+ def client
153
+ self.class.client
154
+ end
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,3 @@
1
+ module Served
2
+ VERSION = '0.1.5'
3
+ end
data/served.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'served/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'served'
8
+ spec.version = Served::VERSION
9
+ spec.authors = ['Jarod Reid']
10
+ spec.email = ['jarod@solidalchemy.com']
11
+
12
+ spec.summary = %q{Served provides an easy to use model layer for communicating with disributed Rails based Services.}
13
+ spec.description = %q{Served provides an easy to use model layer for communicating with disributed Rails based Services.}
14
+ spec.homepage = 'http://github.com/fugufish/served'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = 'exe'
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_dependency 'httparty'
23
+ spec.add_dependency 'activesupport', '>= 3.2'
24
+
25
+ spec.add_development_dependency 'bundler', '~> 1.10'
26
+ spec.add_development_dependency 'rake', '~> 10.0'
27
+ spec.add_development_dependency 'rspec'
28
+ end
metadata ADDED
@@ -0,0 +1,134 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: served
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.5
5
+ platform: ruby
6
+ authors:
7
+ - Jarod Reid
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-09-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httparty
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '3.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '3.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.10'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.10'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Served provides an easy to use model layer for communicating with disributed
84
+ Rails based Services.
85
+ email:
86
+ - jarod@solidalchemy.com
87
+ executables: []
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - ".rspec"
93
+ - ".travis.yml"
94
+ - CODE_OF_CONDUCT.md
95
+ - Gemfile
96
+ - LICENSE.txt
97
+ - README.md
98
+ - Rakefile
99
+ - bin/console
100
+ - bin/setup
101
+ - lib/served.rb
102
+ - lib/served/engine.rb
103
+ - lib/served/http_client.rb
104
+ - lib/served/resource.rb
105
+ - lib/served/resource/base.rb
106
+ - lib/served/version.rb
107
+ - served.gemspec
108
+ homepage: http://github.com/fugufish/served
109
+ licenses:
110
+ - MIT
111
+ metadata: {}
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubyforge_project:
128
+ rubygems_version: 2.4.8
129
+ signing_key:
130
+ specification_version: 4
131
+ summary: Served provides an easy to use model layer for communicating with disributed
132
+ Rails based Services.
133
+ test_files: []
134
+ has_rdoc: