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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bff655df3f7d9258995bd2aa623fff010338981e
4
- data.tar.gz: a55461e6ecfeebd9683394efb7199c6e45db044f
3
+ metadata.gz: 6c093cf970fccbd0cbf10a9e788a955935afe2ca
4
+ data.tar.gz: 434ceec002f574baad3fbf011eeeb9f38f91efe8
5
5
  SHA512:
6
- metadata.gz: 122144bf42ae753bd066237e265dae99a232e15a92cc962815e03177a12e6bf7a4468d59208aff00c9d62aba3cbfaad9a7cfe01a7b23d9676033ee8b7b962c4e
7
- data.tar.gz: 8167ab4e76ac920c90e1dc668886203923ed85ccca1c5c255dac7bf2db0dde181a77be64fc642bf539796172222a5cbb430826da8275fb51c519aacfa987c88b
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
- [![Build Status](https://travis-ci.com/jamesmoriarty/zendesk.svg?token=kWz41FX2t394aCfgBXSy&branch=master)](https://travis-ci.com/jamesmoriarty/zendesk)
3
+ [![Build Status](https://travis-ci.com/jamesmoriarty/zendesk.svg?token=kWz41FX2t394aCfgBXSy&branch=master)](https://travis-ci.com/jamesmoriarty/zendesk) [![Gem Version](https://badge.fury.io/rb/zendesk-james-moriarty.svg)](https://badge.fury.io/rb/zendesk-james-moriarty)
4
4
 
5
- ## Development
6
-
7
- ### Tests
5
+ ## Install
8
6
 
9
7
  ```
10
- rake
8
+ gem install zendesk-james-moriarty
11
9
  ```
12
10
 
13
11
  ### Usage
14
12
 
15
13
  ```
16
- $ ./exe/zendesk
17
- usage: ./exe/zendesk [options]
18
- -f, --files json file paths to load e.g. users.json
19
- -c, --command command expression e.g _id=101
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
- $ ./exe/zendesk -f data/organizations.json -f data/tickets.json -c "_id=101"
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
- ./exe/zendesk -c "_id=101"
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
+ ![alt text](./docs/graphviz.png "Graphviz diagram")
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
@@ -4,34 +4,61 @@ require 'slop'
4
4
 
5
5
  require 'zendesk/version'
6
6
  require 'zendesk/processer'
7
- require 'zendesk/printer/simple'
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', 'json file paths to load e.g. Users.json', default: default_file_paths
17
- opts.string '-c', '--command', 'command expression e.g _id=101'
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
- Printer::Table.print(results)
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 = tokenize command
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 tokenize(command)
20
- exps = command.split(' ')
21
- exps.map { |exp| exp.split('=') }.each_with_object({}) do |(field, value), ast|
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
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Zendesk
4
4
  module Printer
5
- module Simple
5
+ module Json
6
6
  module_function
7
7
 
8
8
  def print(results)
@@ -1,30 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'zendesk/command_parser'
4
- require 'zendesk/strategy/simple'
4
+ require 'zendesk/strategy'
5
5
 
6
6
  module Zendesk
7
7
  module Processor
8
8
  extend self
9
9
 
10
- def process(command, file_paths, strategy = Strategy::Simple)
11
- command_ast = CommandParser.parse(command)
12
- db = strategy.load(file_paths)
13
- results = strategy.exec(db, command_ast)
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
- do_exec_related strategy, db, results
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 do_exec_related(strategy, db, results)
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.exec(db, command_ast, results)
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Zendesk
4
- VERSION = '0.1.0'
4
+ VERSION = '0.1.1'
5
5
  end
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.0
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-16 00:00:00.000000000 Z
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/frozen_hash.rb
167
- - lib/zendesk/printer/simple.rb
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/simple.rb
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
@@ -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