zendesk-james-moriarty 0.1.0 → 0.1.1
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 +4 -4
- data/Gemfile.lock +2 -2
- data/README.md +54 -11
- data/docs/graphviz.png +0 -0
- data/lib/zendesk/command_line.rb +37 -10
- data/lib/zendesk/command_parser.rb +7 -4
- data/lib/zendesk/printer.rb +16 -0
- data/lib/zendesk/printer/{simple.rb → json.rb} +1 -1
- data/lib/zendesk/processer.rb +9 -8
- data/lib/zendesk/strategy.rb +16 -0
- data/lib/zendesk/strategy/ruby.rb +58 -0
- data/lib/zendesk/strategy/sqlite3.rb +17 -0
- data/lib/zendesk/version.rb +1 -1
- metadata +8 -5
- data/lib/zendesk/frozen_hash.rb +0 -19
- data/lib/zendesk/strategy/simple.rb +0 -47
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6c093cf970fccbd0cbf10a9e788a955935afe2ca
|
4
|
+
data.tar.gz: 434ceec002f574baad3fbf011eeeb9f38f91efe8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cb18d346d96019596d0208703b8196a53dac2b356e65c056cad7e9235f7752d7c27e311c0c998a47713cbac3cd0146d839288d6602c592a37303baea34d18530
|
7
|
+
data.tar.gz: 31c0de873ab6b4df5ec610cf40fee3e379f445a73e73b20f1b94678fd2c593b350d9278b60bf6607646542d77e8dde02afafdb6e9227adebdbfd24060b11b4d5
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
zendesk (0.1.0)
|
4
|
+
zendesk-james-moriarty (0.1.0)
|
5
5
|
activesupport (~> 5.0)
|
6
6
|
slop (~> 4.0)
|
7
7
|
terminal-table (~> 1.8.0)
|
@@ -77,7 +77,7 @@ DEPENDENCIES
|
|
77
77
|
rspec (~> 3.0)
|
78
78
|
rubocop (~> 0.71.0)
|
79
79
|
simplecov (~> 0.16.1)
|
80
|
-
zendesk!
|
80
|
+
zendesk-james-moriarty!
|
81
81
|
|
82
82
|
BUNDLED WITH
|
83
83
|
2.0.2
|
data/README.md
CHANGED
@@ -1,29 +1,42 @@
|
|
1
1
|
# Zendesk
|
2
2
|
|
3
|
-
[](https://travis-ci.com/jamesmoriarty/zendesk)
|
3
|
+
[](https://travis-ci.com/jamesmoriarty/zendesk) [](https://badge.fury.io/rb/zendesk-james-moriarty)
|
4
4
|
|
5
|
-
##
|
6
|
-
|
7
|
-
### Tests
|
5
|
+
## Install
|
8
6
|
|
9
7
|
```
|
10
|
-
|
8
|
+
gem install zendesk-james-moriarty
|
11
9
|
```
|
12
10
|
|
13
11
|
### Usage
|
14
12
|
|
15
13
|
```
|
16
|
-
$
|
17
|
-
usage:
|
18
|
-
-f, --files json file paths to load
|
19
|
-
-c, --command command expression
|
14
|
+
$ zendesk
|
15
|
+
usage: zendesk [options]
|
16
|
+
-f, --files json file paths to load
|
17
|
+
-c, --command command expression to execute
|
20
18
|
--version print the version
|
19
|
+
|
20
|
+
examples:
|
21
|
+
|
22
|
+
# search field "_id" for value equal to "101" in "organizations.json".
|
23
|
+
zendesk --command _id=101 --files data/organizations.json
|
24
|
+
|
25
|
+
# search field "domain_names" for value equal to "zentix.com" using default fixtures.
|
26
|
+
zendesk --command domain_names=zentix.com
|
27
|
+
|
28
|
+
# search with multiple command expressions.
|
29
|
+
zendesk --command "_id=101 _id=102" --files data/organizations.json
|
30
|
+
|
31
|
+
# search with multiple file paths.
|
32
|
+
zendesk --command "_id=101" --files data/organizations.json --files data/users.json
|
33
|
+
|
21
34
|
```
|
22
35
|
|
23
36
|
A command with specific files:
|
24
37
|
|
25
38
|
```
|
26
|
-
|
39
|
+
zendesk -f data/organizations.json -f data/tickets.json -c "_id=101"
|
27
40
|
+----------------+----------------------------------------------------------+
|
28
41
|
| Organizations |
|
29
42
|
+----------------+----------------------------------------------------------+
|
@@ -36,7 +49,7 @@ $ ./exe/zendesk -f data/organizations.json -f data/tickets.json -c "_id=101"
|
|
36
49
|
A command with the default fixtures:
|
37
50
|
|
38
51
|
```
|
39
|
-
|
52
|
+
zendesk -c "_id=101"
|
40
53
|
+----------------+----------------------------------------------------------+
|
41
54
|
| Organizations |
|
42
55
|
+----------------+----------------------------------------------------------+
|
@@ -46,10 +59,40 @@ A command with the default fixtures:
|
|
46
59
|
...
|
47
60
|
```
|
48
61
|
|
62
|
+
## Development
|
63
|
+
|
64
|
+
### Tests
|
65
|
+
|
66
|
+
```
|
67
|
+
rake
|
68
|
+
```
|
69
|
+
|
70
|
+
### Usage
|
71
|
+
|
72
|
+
```
|
73
|
+
$ ./exe/zendesk
|
74
|
+
usage: ./exe/zendesk [options]
|
75
|
+
...
|
76
|
+
```
|
77
|
+
|
49
78
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
50
79
|
|
51
80
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
52
81
|
|
82
|
+
## Design
|
83
|
+
|
84
|
+
Below is a diagram illustrating the transforms as vertices and the data as edges.
|
85
|
+
|
86
|
+

|
87
|
+
|
88
|
+
- `LoadFiles` -> `Execute` have a common `Strategy` abstraction to allow for a different underlying implementation. This will hopefully help scale with more data.
|
89
|
+
- `ParseCommand` abstracts user input and give a common command AST input across different strategies.
|
90
|
+
- `Print` can be more abstracted and provide different outputs like JSON, CSV, ...
|
91
|
+
- In an attempt to separate Behaviour and Data:
|
92
|
+
- I've tried to write "pure functions" when possible.
|
93
|
+
- I've been attempting to reduce side effects by making some objects immutable.
|
94
|
+
- I've tried to incorporate things like SOLID without making the code feel anemic.
|
95
|
+
|
53
96
|
## Contributing
|
54
97
|
|
55
98
|
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/zendesk.
|
data/docs/graphviz.png
ADDED
Binary file
|
data/lib/zendesk/command_line.rb
CHANGED
@@ -4,34 +4,61 @@ require 'slop'
|
|
4
4
|
|
5
5
|
require 'zendesk/version'
|
6
6
|
require 'zendesk/processer'
|
7
|
-
require 'zendesk/printer
|
8
|
-
require 'zendesk/printer/table'
|
7
|
+
require 'zendesk/printer'
|
9
8
|
|
10
9
|
module Zendesk
|
11
10
|
module CommandLine
|
12
11
|
extend self
|
13
12
|
|
13
|
+
HELP_TEXT = <<~TXT
|
14
|
+
|
15
|
+
examples:
|
16
|
+
|
17
|
+
# search field "_id" for value equal to "101" in "organizations.json".
|
18
|
+
zendesk --command _id=101 --files data/organizations.json
|
19
|
+
|
20
|
+
# search field "domain_names" for value equal to "zentix.com" using default fixtures.
|
21
|
+
zendesk --command domain_names=zentix.com
|
22
|
+
|
23
|
+
# search with multiple command expressions.
|
24
|
+
zendesk --command "_id=101 _id=102" --files data/organizations.json
|
25
|
+
|
26
|
+
# search with multiple file paths.
|
27
|
+
zendesk --command "_id=101" --files data/organizations.json --files data/users.json
|
28
|
+
|
29
|
+
TXT
|
30
|
+
|
14
31
|
def run
|
15
32
|
opts = Slop.parse do |opts|
|
16
|
-
opts.array '-f', '--files', '
|
17
|
-
opts.string '-c', '--command', '
|
33
|
+
opts.array '-f', '--files', '"path/to/file.json"', default: default_file_paths
|
34
|
+
opts.string '-c', '--command', '"<FIELD>=<VALUE>"'
|
35
|
+
opts.string '-s', '--strategy', '"ruby", "sqlite3" supported', default: 'ruby'
|
36
|
+
opts.string '-p', '--printer', '"table", "json" supported', default: 'table'
|
37
|
+
|
38
|
+
opts.on '-h', '--help' do
|
39
|
+
puts opts
|
40
|
+
|
41
|
+
puts HELP_TEXT
|
18
42
|
|
43
|
+
exit
|
44
|
+
end
|
45
|
+
|
19
46
|
opts.on '--version', 'print the version' do
|
20
47
|
puts Zendesk::VERSION
|
21
48
|
|
22
49
|
exit
|
23
50
|
end
|
24
|
-
end
|
25
51
|
|
26
|
-
if opts[:command].blank?
|
27
|
-
puts opts
|
28
52
|
|
29
|
-
exit
|
30
53
|
end
|
31
54
|
|
32
|
-
results = Zendesk::Processor.process(opts[:command], opts[:files])
|
55
|
+
results = Zendesk::Processor.process(opts[:command], opts[:files], opts[:strategy])
|
56
|
+
|
57
|
+
Zendesk::Printer.get(opts[:printer]).print(results)
|
58
|
+
rescue Exception => e
|
59
|
+
puts e.message
|
33
60
|
|
34
|
-
|
61
|
+
exit
|
35
62
|
end
|
36
63
|
|
37
64
|
private
|
@@ -5,7 +5,7 @@ module Zendesk
|
|
5
5
|
extend self
|
6
6
|
|
7
7
|
def parse(command)
|
8
|
-
command_ast =
|
8
|
+
command_ast = do_parse do_tokenize command
|
9
9
|
|
10
10
|
raise Zendesk::Error, 'invalid command' if command_ast.empty?
|
11
11
|
|
@@ -16,9 +16,12 @@ module Zendesk
|
|
16
16
|
|
17
17
|
private
|
18
18
|
|
19
|
-
def
|
20
|
-
exps = command.split(
|
21
|
-
|
19
|
+
def do_tokenize(command)
|
20
|
+
exps = command.split(/\=| /).each_slice(2)
|
21
|
+
end
|
22
|
+
|
23
|
+
def do_parse(tokens)
|
24
|
+
tokens.each_with_object({}) do |(field, value), ast|
|
22
25
|
ast['='] ||= []
|
23
26
|
ast['='] << [field, value]
|
24
27
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'zendesk/printer/json'
|
4
|
+
require 'zendesk/printer/table'
|
5
|
+
|
6
|
+
module Zendesk
|
7
|
+
module Printer
|
8
|
+
module_function
|
9
|
+
|
10
|
+
def get(printer_string)
|
11
|
+
const_get printer_string.classify
|
12
|
+
rescue NameError => e
|
13
|
+
raise Zendesk::Error, "unknown printer '#{printer_string}'"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/zendesk/processer.rb
CHANGED
@@ -1,30 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'zendesk/command_parser'
|
4
|
-
require 'zendesk/strategy
|
4
|
+
require 'zendesk/strategy'
|
5
5
|
|
6
6
|
module Zendesk
|
7
7
|
module Processor
|
8
8
|
extend self
|
9
9
|
|
10
|
-
def process(
|
11
|
-
command_ast = CommandParser.parse(
|
12
|
-
|
13
|
-
|
10
|
+
def process(command_string, file_paths, strategy_string)
|
11
|
+
command_ast = CommandParser.parse(command_string)
|
12
|
+
strategy = Strategy.get(strategy_string)
|
13
|
+
db = strategy.load_files(file_paths)
|
14
|
+
results = strategy.execute(db, command_ast)
|
14
15
|
|
15
|
-
|
16
|
+
do_execute_related strategy, db, results
|
16
17
|
rescue Errno::ENOENT => e
|
17
18
|
raise Zendesk::Error, e.message
|
18
19
|
end
|
19
20
|
|
20
21
|
private
|
21
22
|
|
22
|
-
def
|
23
|
+
def do_execute_related(strategy, db, results)
|
23
24
|
results.keys.each do |table_name|
|
24
25
|
results[table_name].each do |row|
|
25
26
|
command_ast = CommandParser.parse("#{table_name.chomp('s')}_id=#{row['_id']}")
|
26
27
|
|
27
|
-
results = strategy.
|
28
|
+
results = strategy.execute(db, command_ast, results)
|
28
29
|
end
|
29
30
|
end
|
30
31
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'zendesk/strategy/ruby'
|
4
|
+
require 'zendesk/strategy/sqlite3'
|
5
|
+
|
6
|
+
module Zendesk
|
7
|
+
module Strategy
|
8
|
+
module_function
|
9
|
+
|
10
|
+
def get(strategy_string)
|
11
|
+
const_get strategy_string.classify
|
12
|
+
rescue NameError => e
|
13
|
+
raise Zendesk::Error, "unknown strategy '#{strategy_string}'"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Zendesk
|
6
|
+
module Strategy
|
7
|
+
module Ruby
|
8
|
+
extend self
|
9
|
+
|
10
|
+
def load_files(file_paths)
|
11
|
+
db = Hash.new { |hash, key| hash[key] = [] }
|
12
|
+
|
13
|
+
file_paths.inject(db) do |db, file_path|
|
14
|
+
table_name = File.basename file_path, '.json'
|
15
|
+
table_data = JSON.load File.read file_path
|
16
|
+
|
17
|
+
table_data.each_with_object(db) do |row, db|
|
18
|
+
db[table_name] << row
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def execute(db, command_ast, results = Hash.new { |hash, key| hash[key] = [] })
|
24
|
+
db.keys.each do |table_name|
|
25
|
+
db[table_name].each do |row|
|
26
|
+
command_ast.each do |op, context|
|
27
|
+
matched = match_op(op, context, row)
|
28
|
+
|
29
|
+
results[table_name] << row if matched
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
results
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def match_op(op, context, row)
|
40
|
+
case op
|
41
|
+
when '='
|
42
|
+
context.any? { |(field, value)| match_eq row, field, value }
|
43
|
+
else
|
44
|
+
raise Zendesk::Error, "unknown command \"#{op}\""
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def match_eq(row, field, value)
|
49
|
+
case row[field]
|
50
|
+
when Array
|
51
|
+
row[field].include?(value)
|
52
|
+
else
|
53
|
+
row[field].to_s == value.to_s
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Zendesk
|
4
|
+
module Strategy
|
5
|
+
module Sqlite3
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def load_files(_file_paths)
|
9
|
+
raise NotImplementedError
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute(_db, _command_ast, _results = {})
|
13
|
+
raise NotImplementedError
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/zendesk/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zendesk-james-moriarty
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Moriarty
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-06-
|
11
|
+
date: 2019-06-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -159,15 +159,18 @@ files:
|
|
159
159
|
- data/organizations.json
|
160
160
|
- data/tickets.json
|
161
161
|
- data/users.json
|
162
|
+
- docs/graphviz.png
|
162
163
|
- exe/zendesk
|
163
164
|
- lib/zendesk.rb
|
164
165
|
- lib/zendesk/command_line.rb
|
165
166
|
- lib/zendesk/command_parser.rb
|
166
|
-
- lib/zendesk/
|
167
|
-
- lib/zendesk/printer/
|
167
|
+
- lib/zendesk/printer.rb
|
168
|
+
- lib/zendesk/printer/json.rb
|
168
169
|
- lib/zendesk/printer/table.rb
|
169
170
|
- lib/zendesk/processer.rb
|
170
|
-
- lib/zendesk/strategy
|
171
|
+
- lib/zendesk/strategy.rb
|
172
|
+
- lib/zendesk/strategy/ruby.rb
|
173
|
+
- lib/zendesk/strategy/sqlite3.rb
|
171
174
|
- lib/zendesk/version.rb
|
172
175
|
- zendesk.gemspec
|
173
176
|
homepage: https://github.com/jamesmoriarty/zendesk
|
data/lib/zendesk/frozen_hash.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Zendesk
|
4
|
-
class FrozenHash < Hash
|
5
|
-
def initialize
|
6
|
-
super
|
7
|
-
|
8
|
-
freeze
|
9
|
-
end
|
10
|
-
|
11
|
-
def add(table_name, row)
|
12
|
-
new_data = deep_dup
|
13
|
-
new_data[table_name] ||= []
|
14
|
-
new_data[table_name] << row
|
15
|
-
|
16
|
-
FrozenHash[new_data]
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,47 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'json'
|
4
|
-
|
5
|
-
require 'zendesk/frozen_hash'
|
6
|
-
|
7
|
-
module Zendesk
|
8
|
-
module Strategy
|
9
|
-
module Simple
|
10
|
-
extend self
|
11
|
-
|
12
|
-
def load(file_paths)
|
13
|
-
file_paths.inject(FrozenHash.new) do |db, file_path|
|
14
|
-
table_name = File.basename(file_path, '.json')
|
15
|
-
table_data = JSON.load File.read file_path
|
16
|
-
|
17
|
-
table_data.inject(db) do |db, row|
|
18
|
-
db.add(table_name, row)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def exec(db, command_ast, results = FrozenHash.new)
|
24
|
-
results = do_exec db, command_ast, results
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def do_exec(db, command_ast, results)
|
30
|
-
db.keys.each do |table_name|
|
31
|
-
db[table_name].each do |row|
|
32
|
-
command_ast.each do |type, match|
|
33
|
-
case type
|
34
|
-
when '='
|
35
|
-
results = results.add(table_name, row) if match.any? { |(field, value)| row[field].to_s == value.to_s }
|
36
|
-
else
|
37
|
-
raise Zendesk::Error, "unknown command #{type}"
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
results
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|