custom_tracker 1.0.0

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
+ SHA256:
3
+ metadata.gz: abf4674f2aced8badf74b1d922c6eb88a4900f125890e181f58ee6d349aeaaf3
4
+ data.tar.gz: 16d2709415d57ae08a7663e19c76fd6f8a8380558424e917dcf1133b5431d9b2
5
+ SHA512:
6
+ metadata.gz: 8f31ebd752a9de71c5ad195d6e6bf422d34ad44b7da71a351f77f535f480de5f6018b9875927045dc74d7adc9364e95e7969269ca7eee8fd3ab4452e8f55fa25
7
+ data.tar.gz: 4133a0df76e079118eb0b9b7d2a1e7677f20b1d5c1d52cda840bec64afc8596973f05782f86187e216f8594a07bdd1e267724e0ace0d8bc7123643d9a048e11c
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.5.5
7
+ before_install: gem install bundler -v 2.0.2
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in custom_tracker.gemspec
4
+ gemspec
5
+
6
+ gem "csv", "~> 3.1"
7
+
8
+ gem "date", "~> 2.0"
data/Gemfile.lock ADDED
@@ -0,0 +1,28 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ custom_tracker (1.0.0)
5
+ csv (~> 3.1)
6
+ date (~> 2.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ csv (3.1.1)
12
+ date (2.0.0)
13
+ minitest (5.12.0)
14
+ rake (10.5.0)
15
+
16
+ PLATFORMS
17
+ x64-mingw32
18
+
19
+ DEPENDENCIES
20
+ bundler (~> 2.0)
21
+ csv (~> 3.1)
22
+ custom_tracker!
23
+ date (~> 2.0)
24
+ minitest (~> 5.0)
25
+ rake (~> 10.0)
26
+
27
+ BUNDLED WITH
28
+ 2.0.2
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Fizvlad
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,107 @@
1
+ # CustomTracker
2
+
3
+ This small gem is created to help saving data on some common events.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'custom_tracker'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install custom_tracker
20
+
21
+ ## Usage
22
+
23
+ ### Entries
24
+
25
+ Data bout some event must be stored in `Entry` object. Each of them stores it's unique ID, time of creation and provided data hash:
26
+
27
+ ```ruby
28
+ entry = CustomTracker::Entry.new(
29
+ type: :command_call,
30
+ command: :help,
31
+ author: "username",
32
+ author_status: nil,
33
+ server_id: 8675309
34
+ )
35
+ entry.id # => "5d943aa8a61d"
36
+ entry.time # => 2019-10-02 08:50:32 +0300
37
+ entry.columns # => [:type, :command, :author, :author_status, :server_id]
38
+ ```
39
+ Notice that keys of provided hash must be symbols.
40
+
41
+ ### Tables
42
+
43
+ `Table` objects provide interface for storing and exporting objects:
44
+
45
+ ```ruby
46
+ server_events = CustomTracker::Table.new(
47
+ columns: [:type, :server_id], # List of data which MUST exist in entries
48
+ saving_block: Proc.new do |entries, table|
49
+ # This block recieves array of entries which must be saved somewhere
50
+ CSV.open("table.csv", "a") do |csv|
51
+ entries.each do |entry|
52
+ csv << [ entry.id, entry.time.to_i ] + table.columns.map { |c| entry[c] }
53
+ end
54
+ end
55
+ end
56
+ )
57
+ ```
58
+
59
+ To add event to table simply use method `Table#record`:
60
+
61
+ ```ruby
62
+ server_events.record entry
63
+ server_events.size_unsaved # => 1
64
+ server_events.save # Export recorded entries using block above
65
+ server_events.size_unsaved # => 0
66
+ ```
67
+
68
+ ### Tracker
69
+
70
+ You can handle several tables using `Tracker`:
71
+
72
+ ```ruby
73
+ tracker = CustomTracker::Tracker.new(
74
+ saving_block: Proc.new do |entries, table_sym, table|
75
+ # This block receives name entries to save, table symbol and table itself
76
+ CSV.open("table_#{ table_sym }.csv", "a") do |csv|
77
+ entries.each do |entry|
78
+ csv << [ entry.id, entry.time.to_i ] + table.columns.map { |c| entry[c] }
79
+ end
80
+ end
81
+ end
82
+ )
83
+
84
+ # Adding tables
85
+ tracker.new_table(:command_events, columns: [:type, :command])
86
+ tracker.new_table(:authored_events, columns: [:type, :author, :author_status])
87
+
88
+ # Recording
89
+ tracker.record_all entry
90
+
91
+ # Saving
92
+ tracker.save_all
93
+ ```
94
+
95
+ ## Development
96
+
97
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
98
+
99
+ 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).
100
+
101
+ ## Contributing
102
+
103
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/custom_tracker.
104
+
105
+ ## License
106
+
107
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task :default => :test
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "custom_tracker"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,36 @@
1
+ lib = File.expand_path("lib", __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "custom_tracker/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "custom_tracker"
7
+ spec.version = CustomTracker::VERSION
8
+ spec.authors = ["Fizvlad"]
9
+ spec.email = ["fizvlad@mail.ru"]
10
+
11
+ spec.summary = "A small gem to track custom events and export saved data"
12
+ spec.homepage = "https://github.com/fizvlad/custom-tracker-rb"
13
+ spec.license = "MIT"
14
+
15
+ spec.required_ruby_version = ">= 2.5.0"
16
+
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = "https://github.com/fizvlad/custom-tracker-rb"
19
+ spec.metadata["changelog_uri"] = "https://github.com/fizvlad/custom-tracker-rb/releases"
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
24
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|examples)/}) }
25
+ end
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+
30
+ spec.add_runtime_dependency "csv", "~> 3.1"
31
+ spec.add_runtime_dependency "date", "~> 2.0"
32
+
33
+ spec.add_development_dependency "bundler", "~> 2.0"
34
+ spec.add_development_dependency "rake", "~> 10.0"
35
+ spec.add_development_dependency "minitest", "~> 5.0"
36
+ end
@@ -0,0 +1,11 @@
1
+ require "csv"
2
+ require "date"
3
+
4
+ require "custom_tracker/version"
5
+ require "custom_tracker/entry"
6
+ require "custom_tracker/table"
7
+ require "custom_tracker/tracker"
8
+
9
+ ##
10
+ # Main module of the library.
11
+ module CustomTracker; end
@@ -0,0 +1,79 @@
1
+ module CustomTracker
2
+
3
+ ##
4
+ # Single tracker entry.
5
+ class Entry
6
+ include Enumerable
7
+
8
+ ##
9
+ # Calls the given block once for each pair in data.
10
+ #
11
+ # @yieldparam [Symbol] key
12
+ # @yieldparam [Object] value
13
+ #
14
+ # @return [self]
15
+ def each(&block)
16
+ @data.each &block
17
+ end
18
+
19
+ ##
20
+ # @return [Time] time of entry creation
21
+ attr_reader :time
22
+
23
+ ##
24
+ # @return [String] id of entry
25
+ attr_reader :id
26
+
27
+ ##
28
+ # @return [Array<Symbols>] Array of column names.
29
+ def columns
30
+ @data.keys
31
+ end
32
+
33
+ ##
34
+ # @param sym [Symbol]
35
+ #
36
+ # @return [Object] data from entry.
37
+ def [](sym)
38
+ @data[sym]
39
+ end
40
+
41
+ ##
42
+ # @param sym [Symbol]
43
+ #
44
+ # @return [Boolean] whether entry stores this column.
45
+ def has?(sym)
46
+ @data.has_key?(sym)
47
+ end
48
+
49
+ ##
50
+ # @return [String] human-readable string.
51
+ def to_s
52
+ <<~HEREDOC
53
+ Entry #{@id} from #{@time}. Data: #{@data}
54
+ HEREDOC
55
+ end
56
+
57
+ ##
58
+ # Creates new entry.
59
+ #
60
+ # @param data [Hash<Symbol, Object>]
61
+ def initialize(data)
62
+ @time = Time.now
63
+ @time.freeze
64
+
65
+ # Generating id from current time and random suffix
66
+ @id = (@time.to_i * 65536 + rand(65536)).to_s(16)
67
+ @id.freeze
68
+
69
+ @data = {}
70
+ data.each_pair do |key, value|
71
+ next unless key.is_a? Symbol
72
+ @data[key] = value
73
+ end
74
+ @data.freeze
75
+ end
76
+
77
+ end
78
+
79
+ end
@@ -0,0 +1,99 @@
1
+ module CustomTracker
2
+
3
+ ##
4
+ # A group of entries with similar data.
5
+ class Table
6
+ include Enumerable
7
+
8
+ ##
9
+ # @return [Integer] total amount of entries.
10
+ def size
11
+ size_unsaved + size_saved
12
+ end
13
+
14
+ ##
15
+ # @return [Integer] amount of unsaved entries.
16
+ def size_unsaved
17
+ @unsaved_entries.size
18
+ end
19
+
20
+ ##
21
+ # @return [Integer] amount of saved entries.
22
+ def size_saved
23
+ @size_saved
24
+ end
25
+
26
+ ##
27
+ # @return [Array<Symbol>] Array of column names.
28
+ attr_reader :columns
29
+
30
+ ##
31
+ # Creates new table.
32
+ #
33
+ # @param options [Hash]
34
+ #
35
+ # @option options [Array<Symbol>] columns array of column names all the entries
36
+ # which are added to this table are required to store it.
37
+ # @option options [#call] saving_block callable object which must accept
38
+ # +Array<Entry>+ - array of entries to save and +Table+ - +self+
39
+ def initialize(options)
40
+ @columns = options[:columns].select { |s| s.is_a? Symbol }
41
+ @columns.freeze
42
+
43
+ @saving_block = options[:saving_block]
44
+ unless @saving_block.respond_to? :call
45
+ raise ArgumentError, "saving_block is not responding to call method!", caller
46
+ end
47
+
48
+ @size_saved = 0
49
+ @unsaved_entries = []
50
+ end
51
+
52
+ ##
53
+ # @param entry [Entry]
54
+ #
55
+ # @return [Boolean] whether this entry is acceptable.
56
+ def accepts?(entry)
57
+ @columns.all? { |sym| entry.has? sym }
58
+ end
59
+
60
+ ##
61
+ # Checks whether this entry is acceptable and saves it.
62
+ #
63
+ # @param entry [Entry, Hash<Symbol, Object>] if +Hash+ provided, +Entry+ will
64
+ # be created automatically with {Entry#initialize}.
65
+ # @param options [Hash]
66
+ #
67
+ # @option options [Boolean] instant_save if enabled {Table#save} will be called after adding.
68
+ #
69
+ # @return [Entry, nil] +Entry+ if it was saved or +nil+ if it wasn't.
70
+ def record(entry, options = {})
71
+ entry = Entry.new(entry) if entry.is_a? Hash
72
+
73
+ instant_save = !!options[:instant_save]
74
+
75
+ if accepts? entry
76
+ @unsaved_entries.push(entry)
77
+ save if instant_save
78
+ entry
79
+ else
80
+ nil
81
+ end
82
+ end
83
+
84
+ ##
85
+ # Saves all unsaved entries.
86
+ #
87
+ # @return [Integer] amount of saved entries.
88
+ def save
89
+ @saving_block.call(@unsaved_entries, self)
90
+ re = @unsaved_entries.size
91
+ @size_saved += re
92
+ @unsaved_entries.clear
93
+
94
+ re
95
+ end
96
+
97
+ end
98
+
99
+ end
@@ -0,0 +1,105 @@
1
+ module CustomTracker
2
+
3
+ ##
4
+ # A class to handle several tables.
5
+ class Tracker
6
+
7
+ ##
8
+ # @return [Array<Symbol>] array of table names.
9
+ def tables
10
+ @tables.keys
11
+ end
12
+
13
+ ##
14
+ # Access stored table.
15
+ #
16
+ # @return [Table]
17
+ def [](sym)
18
+ @tables[sym]
19
+ end
20
+
21
+ ##
22
+ # Creates new tracker.
23
+ #
24
+ # @param options [Hash]
25
+ #
26
+ # @option options [#call] saving_block callable object which must accept following
27
+ # parameters: +Array<Entry>+ - entries to save, +Symbol+ - name of table and
28
+ # +Table+ for which this block will be called.
29
+ def initialize(options)
30
+ @saving_block = options[:saving_block]
31
+ unless @saving_block.respond_to? :call
32
+ raise ArgumentError, "saving_block is not responding to call method!", caller
33
+ end
34
+
35
+ @tables = {}
36
+ end
37
+
38
+ ##
39
+ # Create new table and add it to handling.
40
+ #
41
+ # @param sym [Symbol]
42
+ # @param options [Hash]
43
+ #
44
+ # @option options [Array<Symbol>] columns array of column names all the entries
45
+ # which are added to this table are required to store it.
46
+ #
47
+ # @return [Table] created table.
48
+ def new_table(sym, options)
49
+ raise ArgumentError, "sym must be a Symbol", caller unless sym.is_a? Symbol
50
+ raise ArgumentError, "This table already exists", caller if @tables.has_key? sym
51
+ table = Table.new(
52
+ options.merge(
53
+ saving_block: Proc.new do |arr, table_local|
54
+ @saving_block.call(arr, sym, table_local)
55
+ end
56
+ )
57
+ )
58
+ @tables[sym] = table
59
+
60
+ table
61
+ end
62
+
63
+ ##
64
+ # Records entry for every table
65
+ #
66
+ # @param entry [Entry]
67
+ #
68
+ # @return [Integer] amount of tables which registred
69
+ def record_all(entry)
70
+ @tables.values.count { |t| t.record entry }
71
+ end
72
+
73
+ ##
74
+ # Records entry for table.
75
+ #
76
+ # @param table_name [Symbol] name of table.
77
+ # @param entry [Entry]
78
+ #
79
+ # @return [Entry, nil] +Entry+ if it was saved or +nil+ if it wasn't.
80
+ def record(table_name, entry)
81
+ @tables[table_name].record entry
82
+ end
83
+
84
+ ##
85
+ # Saves all the tables.
86
+ #
87
+ # @return [nil]
88
+ def save_all
89
+ @tables.values.each(&:save)
90
+ nil
91
+ end
92
+
93
+ ##
94
+ # Saves the table.
95
+ #
96
+ # @param table_name [Symbol] name of table.
97
+ #
98
+ # @return [Integer] amount of saved entries.
99
+ def save(table_name)
100
+ @tables[table_name].save
101
+ end
102
+
103
+ end
104
+
105
+ end
@@ -0,0 +1,7 @@
1
+ module CustomTracker
2
+
3
+ ##
4
+ # Gem version.
5
+ VERSION = "1.0.0"
6
+
7
+ end
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: custom_tracker
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Fizvlad
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-10-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: csv
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: date
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '5.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '5.0'
83
+ description:
84
+ email:
85
+ - fizvlad@mail.ru
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".travis.yml"
92
+ - Gemfile
93
+ - Gemfile.lock
94
+ - LICENSE.txt
95
+ - README.md
96
+ - Rakefile
97
+ - bin/console
98
+ - bin/setup
99
+ - custom_tracker.gemspec
100
+ - lib/custom_tracker.rb
101
+ - lib/custom_tracker/entry.rb
102
+ - lib/custom_tracker/table.rb
103
+ - lib/custom_tracker/tracker.rb
104
+ - lib/custom_tracker/version.rb
105
+ homepage: https://github.com/fizvlad/custom-tracker-rb
106
+ licenses:
107
+ - MIT
108
+ metadata:
109
+ homepage_uri: https://github.com/fizvlad/custom-tracker-rb
110
+ source_code_uri: https://github.com/fizvlad/custom-tracker-rb
111
+ changelog_uri: https://github.com/fizvlad/custom-tracker-rb/releases
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: 2.5.0
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubygems_version: 3.0.4
128
+ signing_key:
129
+ specification_version: 4
130
+ summary: A small gem to track custom events and export saved data
131
+ test_files: []