nasreddin 0.3.10
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.
- checksums.yaml +7 -0
- data/README.md +42 -0
- data/lib/nasreddin.rb +4 -0
- data/lib/nasreddin/api-server.rb +136 -0
- data/lib/nasreddin/remote_torquebox_adapter.rb +38 -0
- data/lib/nasreddin/resource.rb +175 -0
- data/lib/nasreddin/version.rb +3 -0
- metadata +176 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 14b6167ede8abe24650d6a757cf8559cc8e2855f
|
4
|
+
data.tar.gz: cb9108d4eb76c807370a626c736ece44260892ac
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 83bc41838bb86061abecba46b6d64f101d9135ce620f1d6fe05b22abaf713a571bc4707b2896f82436c1d128c11044394ffbb18250d0699ee9e5f573ef3dcb8a
|
7
|
+
data.tar.gz: 18314db0937c622bb89f01cd41e2d86b19a5830e386450b52bc2b867e81e50d95dd5dca6d6d875a3ea7f371cf156d0e56630ffabe0c4db79ad4cff7e575d05f5
|
data/README.md
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
> "Nasreddin, your donkey has been lost."
|
2
|
+
|
3
|
+
> "Thank goodness I was not on the donkey at the time, or I would be lost too."
|
4
|
+
|
5
|
+
|
6
|
+
## What is Nasreddin?
|
7
|
+
|
8
|
+
Nasreddin Hoca was a wise scolar from 13th century Anatolia. This, however, is a library designed to enable know-nothing
|
9
|
+
distribution of data requests between varying services.
|
10
|
+
|
11
|
+
To connect two services, one needs to include the Nasreddin::APIServer middleware and indicate what resources it is offering:
|
12
|
+
```ruby
|
13
|
+
require 'nasreddin/api-server'
|
14
|
+
|
15
|
+
use Nasreddin::APIServer, resources: %w| users |
|
16
|
+
run MyApp
|
17
|
+
```
|
18
|
+
Then, the consumer can use the Nasreddin::Resource class to generate new classes that will talk to the APIServer when making
|
19
|
+
requests.
|
20
|
+
|
21
|
+
|
22
|
+
An example implementation of Nasreddin::Resource is provided below
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
require 'nasreddin/resource'
|
26
|
+
|
27
|
+
class User < Nasreddin::Resource('users') # name of endpoint for resource
|
28
|
+
end
|
29
|
+
|
30
|
+
```
|
31
|
+
|
32
|
+
|
33
|
+
## Caveats
|
34
|
+
|
35
|
+
Currently, Nasreddin relies on JRuby and TorqueBox/HornetQ.
|
36
|
+
|
37
|
+
|
38
|
+
## License
|
39
|
+
|
40
|
+
Copyright (C) 2012-2013 Burnside Digital
|
41
|
+
|
42
|
+
Licensed under the BSD 2-Clause License. See COPYING for license details.
|
data/lib/nasreddin.rb
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
module Nasreddin
|
5
|
+
|
6
|
+
class APIServer
|
7
|
+
|
8
|
+
def initialize(app, options = {})
|
9
|
+
@app = app
|
10
|
+
@threads = {}
|
11
|
+
@resources = options[:resources]
|
12
|
+
@route_prefix = options[:route_prefix]
|
13
|
+
if @resources
|
14
|
+
@resources.each do |resource|
|
15
|
+
@threads[resource] = Thread.new { Nasreddin::APIServerResource.new(@route_prefix,resource,@app).run }
|
16
|
+
end
|
17
|
+
else
|
18
|
+
$stderr.puts "WARNING: Nasreddin::APIServer is being used without any resources specified!"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def call(env)
|
23
|
+
params = Rack::Request.new(env).params
|
24
|
+
|
25
|
+
if is_heartbeat?(params)
|
26
|
+
res = params['resource'] = params['resources'].pop
|
27
|
+
params["resources.#{res}"] = @resources
|
28
|
+
Nasreddin::Resource(@resource).remote_call(params)
|
29
|
+
else
|
30
|
+
@app.call(env)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def is_heartbeat?(params)
|
35
|
+
params.has_key? '__hearbeat__'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class APIServerResource
|
40
|
+
|
41
|
+
DEFAULT_ENV = {
|
42
|
+
'rack.errors' => $stderr,
|
43
|
+
'rack.input' => StringIO.new,
|
44
|
+
'rack.version' => [1, 1],
|
45
|
+
'rack.multithread' => true,
|
46
|
+
'rack.multiprocess' => true,
|
47
|
+
'rack.run_once' => false,
|
48
|
+
'HTTP_ACCEPT' => 'application/json',
|
49
|
+
'HTTP_USER_AGENT' => 'NasreddinAPI'
|
50
|
+
}
|
51
|
+
|
52
|
+
def initialize(route_prefix,resource,app)
|
53
|
+
@resource = resource
|
54
|
+
@route_prefix = route_prefix
|
55
|
+
@app = app
|
56
|
+
end
|
57
|
+
|
58
|
+
def queue
|
59
|
+
@queue ||= TorqueBox::Messaging::Queue.start("/queues/#{@resource}", durable: false)
|
60
|
+
end
|
61
|
+
|
62
|
+
def run
|
63
|
+
loop do
|
64
|
+
begin
|
65
|
+
queue.receive_and_publish &method(:process_incoming_message)
|
66
|
+
rescue Exception => err
|
67
|
+
$stderr.puts "Error processing request: #{err.class} - #{err.message}"
|
68
|
+
if err.kind_of?(Java::JavaxJms::JMSException)
|
69
|
+
break
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
queue.stop
|
74
|
+
end
|
75
|
+
|
76
|
+
def is_heartbeat?(msg)
|
77
|
+
msg[:params] && msg[:params].has_key?('__heartbeat__')
|
78
|
+
end
|
79
|
+
|
80
|
+
def call(env)
|
81
|
+
@app.call(env)
|
82
|
+
end
|
83
|
+
|
84
|
+
def process_incoming_message(msg)
|
85
|
+
return heartbeat_ok if is_heartbeat?(msg)
|
86
|
+
|
87
|
+
begin
|
88
|
+
status, headers, body = call(env(msg))
|
89
|
+
|
90
|
+
resp = ''
|
91
|
+
body.each { |d| resp += d.to_s }
|
92
|
+
body.close if body.respond_to?(:close)
|
93
|
+
|
94
|
+
rescue Exception => err
|
95
|
+
resp = "#{err.message}\n\n#{err.backtrace.join("\n")}"
|
96
|
+
end
|
97
|
+
|
98
|
+
[status, headers, resp]
|
99
|
+
end
|
100
|
+
|
101
|
+
def heartbeat_ok
|
102
|
+
[200, nil, "OK"]
|
103
|
+
end
|
104
|
+
|
105
|
+
def env(msg)
|
106
|
+
env = DEFAULT_ENV.clone
|
107
|
+
env['rack.url_scheme'] = (msg.delete(:secure) ? 'https' : 'http')
|
108
|
+
method = msg.delete(:method) || 'GET'
|
109
|
+
env['REQUEST_METHOD'] = method.to_s.upcase
|
110
|
+
env['QUERY_STRING'] = queryize(msg.delete(:params)) || ''
|
111
|
+
env['SCRIPT_NAME'] = "/#{@route_prefix}" || ''
|
112
|
+
env['PATH_INFO'] = "/#{@resource}"
|
113
|
+
if ((id = msg.delete(:id)))
|
114
|
+
env['PATH_INFO'] += "/#{id}"
|
115
|
+
end
|
116
|
+
if ((path = msg.delete(:path)))
|
117
|
+
env['PATH_INFO'] += "/#{path}"
|
118
|
+
end
|
119
|
+
env['REQUEST_URI'] = "#{env['SCRIPT_NAME']}#{env['PATH_INFO']}"
|
120
|
+
env.merge!(Hash[msg.map { |k, v| [k.to_s, v] }])
|
121
|
+
env
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
def queryize(params = {})
|
127
|
+
params.map do |key, value|
|
128
|
+
if value.is_a? Array
|
129
|
+
value.map { |v| URI.encode("#{key}[]=#{v}") }
|
130
|
+
else
|
131
|
+
URI.encode("#{key}=#{value}")
|
132
|
+
end
|
133
|
+
end.join('&') unless params.nil?
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#require 'torquebox/messaging'
|
2
|
+
require 'multi_json'
|
3
|
+
|
4
|
+
module Nasreddin
|
5
|
+
class RemoteTorqueboxAdapter
|
6
|
+
attr_accessor :resource, :klass
|
7
|
+
|
8
|
+
def load_data(data,resource, as_objects = true)
|
9
|
+
resp = MultiJson.load(data)
|
10
|
+
resp = resp[@resource] if resp.respond_to?(:keys) && resp.keys.include?(@resource)
|
11
|
+
if resp.kind_of? Array
|
12
|
+
as_objects ? resp.map { |r| @klass.new(r) } : resp
|
13
|
+
else
|
14
|
+
as_objects ? @klass.new(resp) : resp
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def succeded?(status)
|
19
|
+
status != nil && status > 199 && status < 300
|
20
|
+
end
|
21
|
+
|
22
|
+
def queue
|
23
|
+
@queue ||= TorqueBox::Messaging::Queue.start("/queues/#{@resource}", durable: false)
|
24
|
+
end
|
25
|
+
|
26
|
+
def call(params, as_new_objects=false)
|
27
|
+
status, _, data = *(queue.publish_and_receive(params, persistant: false))
|
28
|
+
values = load_data(data,@resource,as_new_objects) if data && !data.empty?
|
29
|
+
[ succeded?(status), values ]
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize(resource, klass)
|
33
|
+
@resource = resource
|
34
|
+
@klass = klass
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
require 'torquebox/messaging'
|
2
|
+
require 'multi_json'
|
3
|
+
|
4
|
+
module Nasreddin
|
5
|
+
|
6
|
+
class SaveError < Exception ; end
|
7
|
+
|
8
|
+
# == Nasreddin Resource
|
9
|
+
# Provides a base class for implementing an API backed data object.
|
10
|
+
# A minimal implementation could be:
|
11
|
+
# class Car < Nasreddin::Resource('cars')
|
12
|
+
# end
|
13
|
+
class Resource
|
14
|
+
class<<self
|
15
|
+
attr_accessor :resource
|
16
|
+
|
17
|
+
def subclasses; (@subclasses ||= []); end
|
18
|
+
|
19
|
+
def inherited(sub)
|
20
|
+
subclasses << sub
|
21
|
+
sub.resource = @resource
|
22
|
+
end
|
23
|
+
|
24
|
+
def remote
|
25
|
+
@remote ||= Nasreddin::RemoteTorqueboxAdapter.new(@resource, self)
|
26
|
+
end
|
27
|
+
|
28
|
+
def remote_call(params = {}, as_objects=true)
|
29
|
+
success, values = remote.call(params, as_objects)
|
30
|
+
values
|
31
|
+
end
|
32
|
+
|
33
|
+
# Allows fetching of all entities without requiring filtering
|
34
|
+
# parameters.
|
35
|
+
def all
|
36
|
+
remote_call({ method: 'GET' }, true)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Allows searching for a specific entity or a collection of
|
40
|
+
# entities that match a certain criteria.
|
41
|
+
# example usage:
|
42
|
+
# Car.find(15)
|
43
|
+
# # => #<Car:0x5fafa486>
|
44
|
+
#
|
45
|
+
# Car.find(make: 'Ford')
|
46
|
+
# # => [ #<Car:0x5fafa486> ]
|
47
|
+
#
|
48
|
+
# Car.find(15, make: 'Ford')
|
49
|
+
# # => [ #<Car:0x5fafa486> ]
|
50
|
+
def find(*args)
|
51
|
+
params = args.last.kind_of?(Hash) ? args.pop : {}
|
52
|
+
id = args.shift
|
53
|
+
|
54
|
+
remote_call({ method: 'GET', id: id, params: params })
|
55
|
+
end
|
56
|
+
|
57
|
+
# Allows creating a new record in one shot
|
58
|
+
# returns true if the record was created
|
59
|
+
# example usage:
|
60
|
+
# Car.create make: 'Ford', model: 'Focus'
|
61
|
+
# # => true or false
|
62
|
+
def create(properties = {})
|
63
|
+
new(properties).save
|
64
|
+
end
|
65
|
+
|
66
|
+
# Allows destroying a resource without finding it
|
67
|
+
# example usage:
|
68
|
+
# Car.destroy(15)
|
69
|
+
# # => true or false
|
70
|
+
def destroy(id)
|
71
|
+
remote_call({ method: 'DELETE', id: id }, false).empty?
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Custom to_json implementation
|
76
|
+
# passes through options to @data
|
77
|
+
def to_json(options={})
|
78
|
+
@data.to_json(options)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Custom as_json implementation
|
82
|
+
# passes through options to @data
|
83
|
+
def as_json(options={})
|
84
|
+
@data.as_json(options)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Checks if the current instance has
|
88
|
+
# already been deleted
|
89
|
+
def deleted?
|
90
|
+
@deleted
|
91
|
+
end
|
92
|
+
|
93
|
+
# Saves the current resource instance
|
94
|
+
# if the instance has an ID it sends a PUT request
|
95
|
+
# otherwise it sends a POST request
|
96
|
+
# will raise an error if the object has been deleted
|
97
|
+
# example usage:
|
98
|
+
# car = Car.find(15)
|
99
|
+
# car.miles += 1500
|
100
|
+
# car.save
|
101
|
+
# # => true or false
|
102
|
+
def save
|
103
|
+
raise SaveError.new("Cannot save a deleted resource") if deleted?
|
104
|
+
|
105
|
+
if @data['id'].to_s.empty?
|
106
|
+
remote_call({ method: 'POST', params: @data })
|
107
|
+
else
|
108
|
+
remote_call({ method: 'PUT', id: @data['id'], params: @data })
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def remote_call(params)
|
113
|
+
success, values = remote.call(params, false)
|
114
|
+
@data = values if values && !values.empty?
|
115
|
+
success
|
116
|
+
end
|
117
|
+
|
118
|
+
# Destroys the current resource instance
|
119
|
+
# example usage:
|
120
|
+
# car = Car.find(15)
|
121
|
+
# car.destroy
|
122
|
+
# # => true or false
|
123
|
+
def destroy
|
124
|
+
if !deleted?
|
125
|
+
@deleted = remote_call({ method: 'DELETE', id: @data['id'] })
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Initialize a new instance
|
130
|
+
# also defines setters for any values given
|
131
|
+
# example usage:
|
132
|
+
# car = Car.new make: 'Ford', model: 'Mustang'
|
133
|
+
# car.respond_to? :make=
|
134
|
+
# # => true
|
135
|
+
def initialize(data={})
|
136
|
+
@deleted = false
|
137
|
+
@data = data
|
138
|
+
@data.each do |key, value|
|
139
|
+
unless respond_to?("#{key.to_s}=")
|
140
|
+
self.class.send(:define_method, "#{key.to_s}=") do |other|
|
141
|
+
@data[key.to_s] = other
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def method_missing(mid, *args, &block)
|
148
|
+
if @data.keys.include?(mid.to_s)
|
149
|
+
@data[mid.to_s]
|
150
|
+
else
|
151
|
+
super
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def respond_to?(mid, include_private=false)
|
156
|
+
@data.keys.include?(mid.to_s) || super
|
157
|
+
end
|
158
|
+
|
159
|
+
private
|
160
|
+
|
161
|
+
def remote
|
162
|
+
self.class.send(:remote)
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
def self.Resource(name)
|
168
|
+
klass = Resource.subclasses.find { |k| k.resource == name }
|
169
|
+
unless klass
|
170
|
+
klass = Class.new(Resource)
|
171
|
+
klass.resource = name
|
172
|
+
end
|
173
|
+
klass
|
174
|
+
end
|
175
|
+
end
|
metadata
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nasreddin
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.10
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Josh Ballanco
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-10-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: torquebox
|
15
|
+
version_requirements: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
requirement: !ruby/object:Gem::Requirement
|
21
|
+
requirements:
|
22
|
+
- - ~>
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: '2.0'
|
25
|
+
prerelease: false
|
26
|
+
type: :runtime
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rack
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.4.1
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - ~>
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: 1.4.1
|
39
|
+
prerelease: false
|
40
|
+
type: :runtime
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: multi_json
|
43
|
+
version_requirements: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.5.0
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ~>
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 1.5.0
|
53
|
+
prerelease: false
|
54
|
+
type: :runtime
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rack-test
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.6.1
|
62
|
+
requirement: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ~>
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: 0.6.1
|
67
|
+
prerelease: false
|
68
|
+
type: :development
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: torquebox-server
|
71
|
+
version_requirements: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '2.0'
|
76
|
+
requirement: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ~>
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '2.0'
|
81
|
+
prerelease: false
|
82
|
+
type: :development
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: kramdown
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.13.7
|
90
|
+
requirement: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ~>
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: 0.13.7
|
95
|
+
prerelease: false
|
96
|
+
type: :development
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: yard
|
99
|
+
version_requirements: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ~>
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.8.2
|
104
|
+
requirement: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ~>
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: 0.8.2
|
109
|
+
prerelease: false
|
110
|
+
type: :development
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: bacon
|
113
|
+
version_requirements: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 1.1.0
|
118
|
+
requirement: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - ~>
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: 1.1.0
|
123
|
+
prerelease: false
|
124
|
+
type: :development
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: mocha-on-bacon
|
127
|
+
version_requirements: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
requirement: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - '>='
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
prerelease: false
|
138
|
+
type: :development
|
139
|
+
description: ' Nasreddin is a library to make distributed calls via HornetQ '
|
140
|
+
email:
|
141
|
+
- jballanc@gmail.com
|
142
|
+
executables: []
|
143
|
+
extensions: []
|
144
|
+
extra_rdoc_files: []
|
145
|
+
files:
|
146
|
+
- ./lib/nasreddin.rb
|
147
|
+
- ./lib/nasreddin/api-server.rb
|
148
|
+
- ./lib/nasreddin/remote_torquebox_adapter.rb
|
149
|
+
- ./lib/nasreddin/resource.rb
|
150
|
+
- ./lib/nasreddin/version.rb
|
151
|
+
- README.md
|
152
|
+
homepage: ''
|
153
|
+
licenses: []
|
154
|
+
metadata: {}
|
155
|
+
post_install_message:
|
156
|
+
rdoc_options: []
|
157
|
+
require_paths:
|
158
|
+
- lib
|
159
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
160
|
+
requirements:
|
161
|
+
- - '>='
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: '0'
|
164
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
165
|
+
requirements:
|
166
|
+
- - '>='
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '0'
|
169
|
+
requirements: []
|
170
|
+
rubyforge_project: ''
|
171
|
+
rubygems_version: 2.1.10
|
172
|
+
signing_key:
|
173
|
+
specification_version: 4
|
174
|
+
summary: A library for making distributed calls via HornetQ
|
175
|
+
test_files: []
|
176
|
+
has_rdoc:
|