juvet 0.0.1

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: 51a223cb59aebbef58cff5014a5e4982c468eed8
4
+ data.tar.gz: 2c835354dc21deaebbe4a1526cfd75cccd15f319
5
+ SHA512:
6
+ metadata.gz: ddbf2a6c64b316fc365fab22a66d47370c9683957719ad9b5323c132eb253691b8db0c42f180ec59791268b9c3031de8d51d44b35da4c4a48558e4fbd647aef8
7
+ data.tar.gz: d5d736c01b01777b7da50de546c0c088f7ddb3a804e46389034f385900dcd8014275defb26e26567a47f81969a770e4bd93ccf74d02a11625f76f320864f212c
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## RUBYGEMS
5
+ *.gem
6
+ .bundle
7
+ vendor/bundle
8
+
9
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org"
2
+ ruby "2.3.0"
3
+
4
+ gemspec
5
+
6
+ group :development, :test do
7
+ gem "rake"
8
+ gem "rspec"
9
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,36 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ juvet (0.0.1)
5
+ redis
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ diff-lcs (1.2.5)
11
+ rake (10.5.0)
12
+ redis (3.2.2)
13
+ rspec (3.4.0)
14
+ rspec-core (~> 3.4.0)
15
+ rspec-expectations (~> 3.4.0)
16
+ rspec-mocks (~> 3.4.0)
17
+ rspec-core (3.4.2)
18
+ rspec-support (~> 3.4.0)
19
+ rspec-expectations (3.4.0)
20
+ diff-lcs (>= 1.2.0, < 2.0)
21
+ rspec-support (~> 3.4.0)
22
+ rspec-mocks (3.4.1)
23
+ diff-lcs (>= 1.2.0, < 2.0)
24
+ rspec-support (~> 3.4.0)
25
+ rspec-support (3.4.1)
26
+
27
+ PLATFORMS
28
+ ruby
29
+
30
+ DEPENDENCIES
31
+ juvet!
32
+ rake
33
+ rspec
34
+
35
+ BUNDLED WITH
36
+ 1.11.2
data/LICENSE.md ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2016 Tatsu, LLC.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,69 @@
1
+ juvet
2
+ =====
3
+
4
+ ## DESCRIPTION
5
+
6
+ A factory and storage mechanism to store your bot information, backed by Redis.
7
+
8
+ A word about the future
9
+ -----------------------
10
+
11
+ The initial intent of this gem is to just store information about the bots you are running. This will in the near future be able to start, stop, and pause bots by turning on/off their senses. In addition by integrating message queuing (right now just by using Redis) will be able to send messages to/from the bots within the factory. This will allow things such as adding health checks, broadcasting messages to all bots, etc.
12
+
13
+ ## USAGE
14
+
15
+ In order to configure Juvet, you will want to specify the repository it will be using. An initializer of some sort would be ideal to place this code in.
16
+
17
+ ```
18
+ Juvet.configure do
19
+ adapter :redis, url: ENV["REDIS_URL"]
20
+ mapping do
21
+ collection :bots do
22
+ repository Juvet::BotRepository
23
+ entity Juvet::Bot
24
+ end
25
+ end
26
+ end
27
+ ```
28
+
29
+ * Creating a bot
30
+
31
+ ```
32
+ Juvet::Bot.create! bot_access_token, team_id: "T12345", status: :active
33
+ ```
34
+
35
+ * Updating a bot
36
+
37
+ ```
38
+ bot = Juvet::Bot.find bot_access_token
39
+ bot.status = :inactive
40
+ bot.update!
41
+ ```
42
+
43
+ * Destroying a bot
44
+
45
+ ```
46
+ Juvet::Bot.destroy! bot_access_token
47
+ ```
48
+
49
+ ## CONTRIBUTING
50
+
51
+ 1. Clone the repository `git clone https://github.com/tatsuio/juvet`
52
+ 1. Create a feature branch `git checkout -b my-awesome-feature`
53
+ 1. Codez!
54
+ 1. Commit your changes (small commits please)
55
+ 1. Push your new branch `git push origin my-awesome-feature`
56
+ 1. Create a pull request `hub pull-request -b tatsuio:master -h tatsuio:my-awesome-feature`
57
+
58
+ ## RELEASING A NEW GEM
59
+
60
+ 1. Bump the VERSION in `lib/juvet/version.rb`
61
+ 1. run `bundle exec rake build`
62
+ 1. Commit changes and push to GitHub
63
+ 1. run `bundle exec rake release`
64
+
65
+ ## LICENSE
66
+
67
+ Copyright (c) 2016, [Tatsu, LLC](http://tatsu.io).
68
+
69
+ This project is licensed under the [MIT License](LICENSE.md).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require "rspec/core/rake_task"
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+
8
+ task :console do
9
+ exec "irb -rubygems -I lib -r juvet.rb"
10
+ end
data/juvet.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "juvet/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "juvet"
8
+ spec.version = Juvet::VERSION
9
+ spec.authors = ["Jamie Wright"]
10
+ spec.email = ["jamie@tatsu.io"]
11
+ spec.summary = "The factory for bots."
12
+ spec.description = "A factory and storage mechanism to store your bot information, backed by Redis."
13
+ spec.homepage = "http://github.com/tatsuio/juvet"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.required_ruby_version = ">= 2.2"
22
+
23
+ spec.add_runtime_dependency("redis")
24
+ end
@@ -0,0 +1,26 @@
1
+ module Juvet
2
+ module Adapters
3
+ class NullAdapter
4
+ def initialize(collection=nil, options={})
5
+ end
6
+
7
+ def create(entity)
8
+ entity
9
+ end
10
+
11
+ def destroy(id)
12
+ end
13
+
14
+ def find(id)
15
+ end
16
+
17
+ def persist(entity)
18
+ entity
19
+ end
20
+
21
+ def update(entity)
22
+ entity
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,53 @@
1
+ require "json"
2
+ require "redis"
3
+
4
+ module Juvet
5
+ module Adapters
6
+ class RedisAdapter
7
+ attr_reader :collection, :redis
8
+
9
+ def initialize(collection, options={})
10
+ @collection = collection
11
+ @redis = Redis.new options
12
+ end
13
+
14
+ def create(entity)
15
+ update_attributes entity
16
+ end
17
+
18
+ def destroy(id)
19
+ redis.del collection_key(id)
20
+ end
21
+
22
+ def find(id)
23
+ attributes = redis.get(collection_key(id))
24
+ return nil if attributes.nil?
25
+ collection.entity.new ({ id: id }).merge(JSON.load(attributes))
26
+ end
27
+
28
+ def persist(entity)
29
+ find(entity.id).nil? ? create(entity) : update_attributes(entity)
30
+ end
31
+
32
+ def update(entity)
33
+ raise EntityNotFoundError if find(entity.id).nil?
34
+ update_attributes entity
35
+ end
36
+
37
+ private
38
+
39
+ def collection_key(id)
40
+ "#{Juvet::String.new(collection.name).underscore}:#{id}"
41
+ end
42
+
43
+ def key(entity)
44
+ collection_key entity.id
45
+ end
46
+
47
+ def update_attributes(entity)
48
+ redis.set key(entity), entity.attributes.to_json
49
+ entity
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,57 @@
1
+ module Juvet
2
+ module Attributable
3
+ def initialize(attributes={})
4
+ initialize! attributes
5
+ attribute! attributes
6
+ end
7
+
8
+ def initialize!(attributes)
9
+ attributes.each { |name, value| set_variable! name, value }
10
+ end
11
+
12
+ def attribute!(attributes)
13
+ (@_attributes ||= []).concat attributes.keys
14
+ attributes.keys.each { |name| define_attribute! name }
15
+ end
16
+
17
+ def attributes
18
+ attributes = {}
19
+ @_attributes.each do |attribute|
20
+ if self.respond_to? attribute
21
+ attributes[attribute] = self.send(attribute)
22
+ end
23
+ end
24
+ attributes
25
+ end
26
+
27
+ private
28
+
29
+ def create_method(name, &block)
30
+ self.class.send(:define_method, name, &block)
31
+ end
32
+
33
+ def define_attribute!(name)
34
+ define_getter!(name)
35
+ define_setter!(name)
36
+ end
37
+
38
+ def define_getter!(name)
39
+ create_method name do
40
+ instance_variable_get("@#{name}")
41
+ end unless respond_to? name
42
+ end
43
+
44
+ def define_setter!(name)
45
+ method = "#{name}="
46
+ create_method method do |value|
47
+ instance_variable_set("@#{name}", value)
48
+ end unless respond_to? method
49
+ end
50
+
51
+ def set_variable!(name, value)
52
+ variable = "@#{name}"
53
+ instance_variable_set("@#{name}", value) \
54
+ unless instance_variable_defined? variable
55
+ end
56
+ end
57
+ end
data/lib/juvet/bot.rb ADDED
@@ -0,0 +1,36 @@
1
+ module Juvet
2
+ class Bot
3
+ include Attributable
4
+
5
+ attr_reader :id
6
+
7
+ class << self
8
+ def create(id, attributes={})
9
+ new id, attributes
10
+ end
11
+
12
+ def create!(id, attributes={})
13
+ BotRepository.create create(id, attributes)
14
+ end
15
+
16
+ def destroy!(id)
17
+ BotRepository.destroy id
18
+ end
19
+
20
+ def find!(id)
21
+ BotRepository.find id
22
+ end
23
+ end
24
+
25
+ def update!(attributes={})
26
+ BotRepository.update self
27
+ end
28
+
29
+ private
30
+
31
+ def initialize(id, attributes={})
32
+ @id = id
33
+ super attributes
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,7 @@
1
+ require_relative "repository"
2
+
3
+ module Juvet
4
+ class BotRepository
5
+ include Repository
6
+ end
7
+ end
@@ -0,0 +1,35 @@
1
+ module Juvet
2
+ class Configuration
3
+ class Adapter
4
+ attr_reader :class_name
5
+ attr_reader :options
6
+ attr_reader :type
7
+
8
+ def initialize(options={})
9
+ opts = (options || {}).dup
10
+
11
+ @type = opts.delete :type
12
+ @options = opts
13
+ @class_name = Juvet::String.new("#{type}_adapter").classify
14
+ end
15
+
16
+ def build(mapper)
17
+ load_adapter
18
+ instantiate_adapter mapper
19
+ end
20
+
21
+ private
22
+
23
+ def load_adapter
24
+ require "juvet/adapters/#{type}_adapter"
25
+ rescue LoadError => e
26
+ raise LoadError.new("Cannot find Juvet adapter '#{type}' (#{e.message})")
27
+ end
28
+
29
+ def instantiate_adapter(mapper)
30
+ klass = Juvet::Adapters.const_get(class_name)
31
+ klass.new(mapper.collection_for_repository(klass), options)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,15 @@
1
+ require "juvet/mapper"
2
+
3
+ module Juvet
4
+ class Configuration
5
+ class Mapping
6
+ def initialize(&block)
7
+ @block = block
8
+ end
9
+
10
+ def build
11
+ Juvet::Mapper.new &@block
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,20 @@
1
+ require_relative "configuration/adapter"
2
+ require_relative "configuration/mapping"
3
+
4
+ module Juvet
5
+ class Configuration
6
+ attr_reader :adapter
7
+
8
+ def adapter=(options)
9
+ @adapter ||= Juvet::Configuration::Adapter.new(options)
10
+ end
11
+
12
+ def mapping(&block)
13
+ @mapping ||= Juvet::Configuration::Mapping.new(&block)
14
+ end
15
+
16
+ def load!
17
+ adapter.build mapping.build
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,4 @@
1
+ module Juvet
2
+ class EntityNotFoundError < RuntimeError
3
+ end
4
+ end
@@ -0,0 +1,28 @@
1
+ module Juvet
2
+ class Mapper
3
+ class Collection
4
+ attr_reader :name
5
+
6
+ def initialize(name, &block)
7
+ @name = name
8
+ instance_eval(&block) if block_given?
9
+ end
10
+
11
+ def entity(klass=nil)
12
+ if klass
13
+ @entity = klass
14
+ else
15
+ @entity
16
+ end
17
+ end
18
+
19
+ def repository(klass=nil)
20
+ if klass
21
+ @repository = klass
22
+ else
23
+ @repository
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,21 @@
1
+ require_relative "mapper/collection"
2
+
3
+ module Juvet
4
+ class Mapper
5
+ attr_reader :collections
6
+
7
+ def initialize(&block)
8
+ @collections = {}
9
+
10
+ instance_eval(&block) if block_given?
11
+ end
12
+
13
+ def collection(name, &block)
14
+ collections[name] = Juvet::Mapper::Collection.new name, &block
15
+ end
16
+
17
+ def collection_for_repository(klass)
18
+ collections.values.find { |collection| collection.repository == klass }
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,43 @@
1
+ require_relative "adapters/null_adapter"
2
+
3
+ module Juvet
4
+ module Repository
5
+ def self.included(base)
6
+ base.class_eval do
7
+ extend ClassMethods
8
+
9
+ self.adapter = Adapters::NullAdapter.new
10
+ end
11
+ end
12
+
13
+ module ClassMethods
14
+ def adapter
15
+ @adapter
16
+ end
17
+
18
+ def adapter=(adapter)
19
+ @adapter = adapter
20
+ end
21
+
22
+ def create(entity)
23
+ adapter.create entity
24
+ end
25
+
26
+ def destroy(id)
27
+ adapter.destroy id
28
+ end
29
+
30
+ def find(id)
31
+ adapter.find id
32
+ end
33
+
34
+ def persist(entity)
35
+ adapter.persist entity
36
+ end
37
+
38
+ def update(entity)
39
+ adapter.update entity
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,20 @@
1
+ module Juvet
2
+ class String
3
+ def initialize(string)
4
+ @string = string.to_s
5
+ end
6
+
7
+ def classify
8
+ string.split("_").map{ |w| w.capitalize }.join
9
+ end
10
+
11
+ def underscore
12
+ modified = string.gsub(/(.)([A-Z])/,'\1_\2')
13
+ modified.downcase
14
+ end
15
+
16
+ private
17
+
18
+ attr_reader :string
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ module Juvet
2
+ VERSION = "0.0.1"
3
+ end
data/lib/juvet.rb ADDED
@@ -0,0 +1,19 @@
1
+ require_relative "juvet/attributable"
2
+ require_relative "juvet/bot"
3
+ require_relative "juvet/bot_repository"
4
+ require_relative "juvet/configuration"
5
+ require_relative "juvet/entity_not_found_error"
6
+ require_relative "juvet/mapper"
7
+ require_relative "juvet/repository"
8
+ require_relative "juvet/string"
9
+
10
+ module Juvet
11
+ def self.configuration
12
+ @configuration ||= Juvet::Configuration.new
13
+ end
14
+
15
+ def self.configure
16
+ yield configuration if block_given?
17
+ configuration.load!
18
+ end
19
+ end
@@ -0,0 +1,28 @@
1
+ describe Juvet::Adapters::NullAdapter do
2
+ let(:entity) { Object.new }
3
+ subject { described_class.new }
4
+
5
+ describe "#create" do
6
+ it "simply returns the entity" do
7
+ expect(subject.create(entity)).to eq entity
8
+ end
9
+ end
10
+
11
+ describe "#find" do
12
+ it "returns nil" do
13
+ expect(subject.find("blah")).to be_nil
14
+ end
15
+ end
16
+
17
+ describe "#persist" do
18
+ it "simply returns the entity" do
19
+ expect(subject.persist(entity)).to eq entity
20
+ end
21
+ end
22
+
23
+ describe "#update" do
24
+ it "simply returns the entity" do
25
+ expect(subject.update(entity)).to eq entity
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,92 @@
1
+ require "json"
2
+ require "./lib/juvet/adapters/redis_adapter"
3
+
4
+ describe Juvet::Adapters::RedisAdapter do
5
+ class Entity
6
+ include Juvet::Attributable
7
+
8
+ attr_accessor :id
9
+ attr_accessor :blah
10
+
11
+ def attributes
12
+ { blah: blah }
13
+ end
14
+ end
15
+
16
+ let(:collection) { double(:collection, name: :entities, entity: Entity) }
17
+ let(:entity) { Entity.new id: 123 }
18
+ let(:url) { "redis://localhost:6379" }
19
+ subject { described_class.new collection, url: url, db: 15 }
20
+
21
+ before(:all) { @redis = Redis.new db: 15 }
22
+ after(:all) { @redis.flushdb }
23
+
24
+ describe "#create" do
25
+ it "stores the entity in the redis store" do
26
+ result = subject.create entity
27
+
28
+ expect(result).to eq entity
29
+ expect(@redis.get("entities:123")).to eq(JSON.generate({ blah: nil }))
30
+ end
31
+ end
32
+
33
+ describe "#destroy" do
34
+ it "removes the entity from the redis store" do
35
+ id = subject.create(entity).id
36
+ subject.destroy id
37
+
38
+ expect(@redis.get("entities:123")).to be_nil
39
+ end
40
+ end
41
+
42
+ describe "#find" do
43
+ it "finds the entity based on the id from the redis store" do
44
+ subject.create entity
45
+ result = subject.find entity.id
46
+
47
+ expect(result.id).to eq entity.id
48
+ end
49
+
50
+ it "returns nil if the entity can't be found" do
51
+ result = subject.find 789
52
+
53
+ expect(result).to be_nil
54
+ end
55
+ end
56
+
57
+ describe "#persist" do
58
+ it "creates the entity if it's new" do
59
+ entity = Entity.new id: 531
60
+ result = subject.persist entity
61
+
62
+ expect(result).to eq entity
63
+ expect(@redis.get("entities:531")).to eq(JSON.generate({ blah: nil }))
64
+ end
65
+
66
+ it "updates the entity if it exists" do
67
+ created = subject.create entity
68
+ created.blah = "bleh"
69
+ result = subject.persist created
70
+
71
+ expect(result).to eq entity
72
+ expect(@redis.get("entities:123")).to eq(JSON.generate({ blah: "bleh" }))
73
+ end
74
+ end
75
+
76
+ describe "#update" do
77
+ it "updates the entity in the redis store" do
78
+ created = subject.create entity
79
+ created.blah = "bleh"
80
+ result = subject.update created
81
+
82
+ expect(result).to eq entity
83
+ expect(@redis.get("entities:123")).to eq(JSON.generate({ blah: "bleh" }))
84
+ end
85
+
86
+ it "throws an exception if the entity is not already stored" do
87
+ entity = Entity.new id: 456
88
+
89
+ expect { subject.update entity }.to raise_error Juvet::EntityNotFoundError
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,85 @@
1
+ describe Juvet::Attributable do
2
+ class Ava
3
+ include Juvet::Attributable
4
+ end
5
+
6
+ describe "#attributes" do
7
+ subject { Ava.new name: "Ava", model: 5.9 }
8
+
9
+ it "returns a hash of the objects public getters and their values" do
10
+ expect(subject.attributes).to eq({ name: "Ava", model: 5.9 })
11
+ end
12
+ end
13
+
14
+ describe "#initialize" do
15
+ it "has a default initializer to accept attributes" do
16
+ expect { Ava.new name: "Ava" }.to_not raise_error
17
+ end
18
+ end
19
+
20
+ describe "#initialize!" do
21
+ subject { Ava.new name: "Ava", age: nil }
22
+
23
+ it "initializes instance variables" do
24
+ expect(subject.instance_variable_get("@name")).to eq "Ava"
25
+ end
26
+
27
+ it "does not override any existing instance variables" do
28
+ subject = Ava.new name: "Ava"
29
+ subject.instance_variable_set "@name", "Blah"
30
+ subject.initialize! name: "Ava"
31
+
32
+ expect(subject.instance_variable_get("@name")).to eq "Blah"
33
+ end
34
+ end
35
+
36
+ describe "#attribute!" do
37
+ subject { Ava.new name: "Ava", age: nil }
38
+
39
+ it "defines the getters for the attributes" do
40
+ expect(subject).to respond_to :name
41
+ end
42
+
43
+ it "responds to the getters" do
44
+ expect(subject.name).to eq "Ava"
45
+ end
46
+
47
+ it "does not override existing getters" do
48
+ class Ava
49
+ include Juvet::Attributable
50
+
51
+ def name
52
+ "Blah"
53
+ end
54
+ end
55
+ subject = Ava.new name: "Ava"
56
+
57
+ expect(subject.name).to eq "Blah"
58
+ end
59
+
60
+ it "defines the setters for the attributes" do
61
+ expect(subject).to respond_to :age=
62
+ end
63
+
64
+ it "has working setters" do
65
+ subject.age = 21
66
+ expect(subject.age).to eq 21
67
+ end
68
+
69
+ it "does not override existing setters" do
70
+ class Foo
71
+ include Juvet::Attributable
72
+ attr_reader :real_name
73
+
74
+ def name=(value)
75
+ @real_name = value
76
+ end
77
+ end
78
+ subject = Foo.new name: "Ava"
79
+ subject.name = "Athena"
80
+
81
+ expect(subject.real_name).to eq "Athena"
82
+ expect(subject.name).to eq "Ava"
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,61 @@
1
+ describe Juvet::Bot do
2
+ describe ".create" do
3
+ subject do
4
+ described_class.create "xoxb-blah", team_id: "Blah",
5
+ name: "blah"
6
+ end
7
+
8
+ it "creates an instance of the class" do
9
+ expect(subject).to be_an_instance_of described_class
10
+ end
11
+
12
+ it "assigns the id" do
13
+ expect(subject.id).to eq "xoxb-blah"
14
+ end
15
+
16
+ it "defines getters for the attributes" do
17
+ expect(subject.team_id).to eq "Blah"
18
+ expect(subject.name).to eq "blah"
19
+ end
20
+
21
+ it "defines setters for the attributes" do
22
+ subject.name = "Thor!"
23
+
24
+ expect(subject.name).to eq "Thor!"
25
+ end
26
+ end
27
+
28
+ describe ".create!" do
29
+ it "stores the created instance in the repository" do
30
+ expect(Juvet::BotRepository).to receive(:create).with Juvet::Bot
31
+ described_class.create! "blah", name: "blah"
32
+ end
33
+ end
34
+
35
+ describe ".destroy!" do
36
+ let!(:bot) { described_class.create! "xoxb-blah", team_id: "Blah" }
37
+
38
+ it "removes the instance from the repository" do
39
+ expect(Juvet::BotRepository).to receive(:destroy).with "xoxb-blah"
40
+ described_class.destroy! bot.id
41
+ end
42
+ end
43
+
44
+ describe ".find" do
45
+ let!(:bot) { described_class.create! "xoxb-blah", team_id: "Blah" }
46
+
47
+ it "creates an instance from the repository" do
48
+ expect(Juvet::BotRepository).to receive(:find).with "xoxb-blah"
49
+ described_class.find! bot.id
50
+ end
51
+ end
52
+
53
+ describe "#update!" do
54
+ let!(:bot) { described_class.create! "xoxb-blah", team_id: "Blah" }
55
+
56
+ it "updates the instance in the repository" do
57
+ expect(Juvet::BotRepository).to receive(:update).with bot
58
+ bot.update! team_id: "Bleh"
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,39 @@
1
+ describe Juvet::Configuration::Adapter do
2
+ describe "#type" do
3
+ it "sets the type from the options" do
4
+ subject = described_class.new type: :null
5
+ expect(subject.type).to eq :null
6
+ end
7
+ end
8
+
9
+ describe "#options" do
10
+ it "includes any additional options initialized" do
11
+ subject = described_class.new type: :nil, blah: :bleh
12
+ expect(subject.options).to eq({ blah: :bleh })
13
+ end
14
+ end
15
+
16
+ describe "#class_name" do
17
+ it "creates a class name from the type" do
18
+ subject = described_class.new type: :null
19
+ expect(subject.class_name).to eq "NullAdapter"
20
+ end
21
+ end
22
+
23
+ describe "#build" do
24
+ let(:mapper) { double(:mapper, collection_for_repository: nil) }
25
+ subject { described_class.new type: :null }
26
+
27
+ it "creates an instance of the adapter" do
28
+ adapter = subject.build mapper
29
+
30
+ expect(adapter).to be_instance_of Juvet::Adapters::NullAdapter
31
+ end
32
+
33
+ it "returns a load error if the adapter type cannot be loaded" do
34
+ subject = described_class.new type: :blah
35
+
36
+ expect { subject.build(mapper) }.to raise_error LoadError
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,18 @@
1
+ describe Juvet::Configuration::Mapping do
2
+ describe "#build" do
3
+ let(:blk) do
4
+ Proc.new {
5
+ collection :widgets do
6
+ end
7
+ }
8
+ end
9
+ subject { described_class.new &blk }
10
+
11
+ it "creates a mapper from a block" do
12
+ result = subject.build
13
+
14
+ expect(result).to be_an_instance_of Juvet::Mapper
15
+ expect(result.collections.length).to eq 1
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,31 @@
1
+ describe Juvet::Configuration do
2
+ subject { described_class.new }
3
+
4
+ it "has a default repository adapter" do
5
+ subject.adapter = nil
6
+ expect(subject.adapter).to be_instance_of Juvet::Configuration::Adapter
7
+ end
8
+
9
+ it "has a default mapping" do
10
+ expect(subject.mapping).to be_instance_of Juvet::Configuration::Mapping
11
+ end
12
+
13
+ describe "#load!" do
14
+ subject { described_class.new }
15
+
16
+ before(:each) do
17
+ subject.adapter = { type: :null }
18
+ subject.mapping do; end
19
+ end
20
+
21
+ it "builds the mapping" do
22
+ expect(subject.mapping).to receive(:build).and_call_original
23
+ subject.load!
24
+ end
25
+
26
+ it "builds the adapter" do
27
+ expect(subject.adapter).to receive(:build).with(Juvet::Mapper)
28
+ subject.load!
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,19 @@
1
+ describe Juvet::Mapper::Collection do
2
+ describe "#initialize" do
3
+ it "provides a name" do
4
+ subject = described_class.new :widgets
5
+
6
+ expect(subject.name).to eq :widgets
7
+ end
8
+
9
+ it "executes the block if one is provided" do
10
+ subject = described_class.new(:widgets) do
11
+ entity Object
12
+ repository Object
13
+ end
14
+
15
+ expect(subject.entity).to eq Object
16
+ expect(subject.repository).to eq Object
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,47 @@
1
+ describe Juvet::Mapper do
2
+ describe "#initialize" do
3
+ it "generates collections based on the block" do
4
+ subject = described_class.new do
5
+ collection :widgets do; end
6
+ end
7
+
8
+ expect(subject.collections.length).to eq 1
9
+ expect(subject.collections).to have_key :widgets
10
+ end
11
+ end
12
+
13
+ describe "#collection" do
14
+ subject { described_class.new }
15
+
16
+ it "adds a collection with the block" do
17
+ subject.collection(:widgets) do; end
18
+
19
+ expect(subject.collections[:widgets]).to \
20
+ be_instance_of Juvet::Mapper::Collection
21
+ end
22
+ end
23
+
24
+ describe "#collection_for_repository" do
25
+ class WidgetRepository; end
26
+ let(:subject) do
27
+ described_class.new do
28
+ collection :widgets do
29
+ repository WidgetRepository
30
+ end
31
+ end
32
+ end
33
+
34
+ it "returns the collection for the first one that specifies the repository" do
35
+ result = subject.collection_for_repository WidgetRepository
36
+
37
+ expect(result.name).to eq :widgets
38
+ expect(result.repository).to eq WidgetRepository
39
+ end
40
+
41
+ it "returns nil if the repository is not found" do
42
+ result = subject.collection_for_repository Object
43
+
44
+ expect(result).to be_nil
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,49 @@
1
+ describe Juvet::Repository do
2
+ class Repository
3
+ include Juvet::Repository
4
+ end
5
+
6
+ it "defaults to using the NullAdapter" do
7
+ expect(Repository.adapter).to be_instance_of Juvet::Adapters::NullAdapter
8
+ end
9
+
10
+ describe ".create" do
11
+ it "passes creation to the adapter" do
12
+ object = Object.new
13
+ expect(Repository.adapter).to receive(:create).with object
14
+ Repository.create object
15
+ end
16
+ end
17
+
18
+ describe ".destroy" do
19
+ it "passes the destroying to the adapter" do
20
+ id = "123"
21
+ expect(Repository.adapter).to receive(:destroy).with id
22
+ Repository.destroy id
23
+ end
24
+ end
25
+
26
+ describe ".find" do
27
+ it "passes the finding to the adapter" do
28
+ id = "123"
29
+ expect(Repository.adapter).to receive(:find).with id
30
+ Repository.find id
31
+ end
32
+ end
33
+
34
+ describe ".persist" do
35
+ it "passes persitance to the adapter" do
36
+ object = Object.new
37
+ expect(Repository.adapter).to receive(:persist).with object
38
+ Repository.persist object
39
+ end
40
+ end
41
+
42
+ describe ".update" do
43
+ it "passes updating to the adapter" do
44
+ object = Object.new
45
+ expect(Repository.adapter).to receive(:update).with object
46
+ Repository.update object
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,13 @@
1
+ describe Juvet::String do
2
+ describe "#classify" do
3
+ it "converts an underscored string to a camel case word" do
4
+ expect(described_class.new("this_is_fine").classify).to eq "ThisIsFine"
5
+ end
6
+ end
7
+
8
+ describe "#underscore" do
9
+ it "converts camel case to underscore" do
10
+ expect(described_class.new("ThisIsFine").underscore).to eq "this_is_fine"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,20 @@
1
+ describe Juvet do
2
+ describe ".configuration" do
3
+ it "returns a new instance of the configuration" do
4
+ expect(described_class.configuration).to be_instance_of Juvet::Configuration
5
+ end
6
+ end
7
+
8
+ describe ".configure" do
9
+ it "yields configuration" do
10
+ allow(described_class.configuration).to receive(:load!)
11
+ expect { |b| described_class.configure &b }.to \
12
+ yield_with_args Juvet::Configuration
13
+ end
14
+
15
+ it "loads the configuration" do
16
+ expect(described_class.configuration).to receive(:load!)
17
+ described_class.configure
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,14 @@
1
+ require "juvet"
2
+
3
+ RSpec.configure do |config|
4
+ config.expect_with :rspec do |expectations|
5
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
6
+ end
7
+
8
+ config.mock_with :rspec do |mocks|
9
+ mocks.verify_partial_doubles = true
10
+ end
11
+
12
+ config.filter_run :focus
13
+ config.run_all_when_everything_filtered = true
14
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: juvet
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jamie Wright
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-02-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: redis
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
+ description: A factory and storage mechanism to store your bot information, backed
28
+ by Redis.
29
+ email:
30
+ - jamie@tatsu.io
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - ".gitignore"
36
+ - ".rspec"
37
+ - Gemfile
38
+ - Gemfile.lock
39
+ - LICENSE.md
40
+ - README.md
41
+ - Rakefile
42
+ - juvet.gemspec
43
+ - lib/juvet.rb
44
+ - lib/juvet/adapters/null_adapter.rb
45
+ - lib/juvet/adapters/redis_adapter.rb
46
+ - lib/juvet/attributable.rb
47
+ - lib/juvet/bot.rb
48
+ - lib/juvet/bot_repository.rb
49
+ - lib/juvet/configuration.rb
50
+ - lib/juvet/configuration/adapter.rb
51
+ - lib/juvet/configuration/mapping.rb
52
+ - lib/juvet/entity_not_found_error.rb
53
+ - lib/juvet/mapper.rb
54
+ - lib/juvet/mapper/collection.rb
55
+ - lib/juvet/repository.rb
56
+ - lib/juvet/string.rb
57
+ - lib/juvet/version.rb
58
+ - spec/juvet/adapters/null_adapter_spec.rb
59
+ - spec/juvet/adapters/redis_adapter_spec.rb
60
+ - spec/juvet/attributable_spec.rb
61
+ - spec/juvet/bot_spec.rb
62
+ - spec/juvet/configuration/adapter_spec.rb
63
+ - spec/juvet/configuration/mapping_spec.rb
64
+ - spec/juvet/configuration_spec.rb
65
+ - spec/juvet/mapper/collection_spec.rb
66
+ - spec/juvet/mapper_spec.rb
67
+ - spec/juvet/repository_spec.rb
68
+ - spec/juvet/string_spec.rb
69
+ - spec/juvet_spec.rb
70
+ - spec/spec_helper.rb
71
+ homepage: http://github.com/tatsuio/juvet
72
+ licenses:
73
+ - MIT
74
+ metadata: {}
75
+ post_install_message:
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '2.2'
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ requirements: []
90
+ rubyforge_project:
91
+ rubygems_version: 2.5.1
92
+ signing_key:
93
+ specification_version: 4
94
+ summary: The factory for bots.
95
+ test_files:
96
+ - spec/juvet/adapters/null_adapter_spec.rb
97
+ - spec/juvet/adapters/redis_adapter_spec.rb
98
+ - spec/juvet/attributable_spec.rb
99
+ - spec/juvet/bot_spec.rb
100
+ - spec/juvet/configuration/adapter_spec.rb
101
+ - spec/juvet/configuration/mapping_spec.rb
102
+ - spec/juvet/configuration_spec.rb
103
+ - spec/juvet/mapper/collection_spec.rb
104
+ - spec/juvet/mapper_spec.rb
105
+ - spec/juvet/repository_spec.rb
106
+ - spec/juvet/string_spec.rb
107
+ - spec/juvet_spec.rb
108
+ - spec/spec_helper.rb