zendesk-james-moriarty 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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