groupie 0.3.0 → 0.4.0
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 +7 -0
- data/.github/dependabot.yml +21 -0
- data/.github/workflows/gem.yml +16 -0
- data/.github/workflows/rspec.yml +21 -0
- data/.github/workflows/rubocop.yml +26 -0
- data/.gitignore +11 -1
- data/.rspec +3 -0
- data/.rubocop.yml +38 -0
- data/CHANGELOG.md +86 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +67 -0
- data/LICENSE.txt +21 -0
- data/README.md +121 -0
- data/Rakefile +7 -48
- data/bin/console +15 -0
- data/bin/rubocop +2 -0
- data/bin/setup +9 -0
- data/groupie.gemspec +36 -0
- data/lib/groupie/core_ext/string.rb +6 -6
- data/lib/groupie/group.rb +8 -2
- data/lib/groupie/version.rb +10 -0
- data/lib/groupie.rb +105 -58
- metadata +53 -85
- data/.document +0 -5
- data/LICENSE +0 -20
- data/VERSION +0 -1
- data/readme.rdoc +0 -24
- data/spec/fixtures/ham/email_ham1.txt +0 -13
- data/spec/fixtures/ham/spam.la-44116217.txt +0 -79
- data/spec/fixtures/spam/email_spam1.txt +0 -5
- data/spec/fixtures/spam/email_spam2.txt +0 -7
- data/spec/fixtures/spam/spam.la-44118014.txt +0 -73
- data/spec/groupie/core_ext/string_spec.rb +0 -37
- data/spec/groupie/group_spec.rb +0 -37
- data/spec/groupie_spec.rb +0 -163
- data/spec/spec_helper.rb +0 -1
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2bbc9cfb580ee027b67d88ac1d22d58b864edbf4c8bed8544748a0d5a35c9526
|
4
|
+
data.tar.gz: ce283b2269613471da0ac4cc14734b1092afe798c9e81337bc676eb6b2964da9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c566f577e7fe83e0e403f4e271f5176d05a00204b0b1bf90a6c40379f5da2924910f4674ea89b2986c36bec17f989ea4f21f381bf8fd75cd679e6f78d95a0472
|
7
|
+
data.tar.gz: bab39365fa7ac4f4a665a803454b223749b917ba3e3c55c821e7714d66d7a6a06c35d9982c8bddeee27e2c8c232922e0f64c3ced84401e350cdf9540e566ac49
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# https://docs.github.com/en/github/administering-a-repository/keeping-your-dependencies-updated-automatically
|
2
|
+
# There's a lot of options, but for now let's keep it simple.
|
3
|
+
# Check every week (Monday 5:00 CET by default) for updates.
|
4
|
+
# Each package manager gets 5 non-security updates by default.
|
5
|
+
# Security updates bypass most configuration here and show up when found.
|
6
|
+
version: 2
|
7
|
+
updates:
|
8
|
+
- package-ecosystem: github-actions
|
9
|
+
# Github Actions are checked for updates
|
10
|
+
directory: '/'
|
11
|
+
schedule:
|
12
|
+
interval: weekly
|
13
|
+
- package-ecosystem: bundler
|
14
|
+
# Bundler handles Ruby dependencies
|
15
|
+
directory: '/'
|
16
|
+
schedule:
|
17
|
+
interval: weekly
|
18
|
+
versioning-strategy: increase-if-necessary
|
19
|
+
allow:
|
20
|
+
- dependency-type: direct
|
21
|
+
- dependency-type: indirect
|
@@ -0,0 +1,16 @@
|
|
1
|
+
name: Gem building
|
2
|
+
|
3
|
+
on: [ pull_request ]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
build:
|
7
|
+
runs-on: ubuntu-latest
|
8
|
+
steps:
|
9
|
+
- uses: actions/checkout@v2
|
10
|
+
- name: Set up Ruby
|
11
|
+
uses: ruby/setup-ruby@v1
|
12
|
+
with:
|
13
|
+
ruby-version: 3.0
|
14
|
+
bundler-cache: true
|
15
|
+
- name: Build the gem
|
16
|
+
run: bundle exec rake build
|
@@ -0,0 +1,21 @@
|
|
1
|
+
name: RSpec
|
2
|
+
|
3
|
+
on: [ push, pull_request ]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
build:
|
7
|
+
runs-on: ubuntu-latest
|
8
|
+
strategy:
|
9
|
+
matrix:
|
10
|
+
# Maintained versions: 2.7 and 3.0
|
11
|
+
# Security updates only: 2.6
|
12
|
+
ruby: [ 2.6, 2.7, 3.0 ]
|
13
|
+
steps:
|
14
|
+
- uses: actions/checkout@v2
|
15
|
+
- name: Set up Ruby
|
16
|
+
uses: ruby/setup-ruby@v1
|
17
|
+
with:
|
18
|
+
ruby-version: ${{ matrix.ruby }}
|
19
|
+
bundler-cache: true
|
20
|
+
- name: Run the tests
|
21
|
+
run: bundle exec rspec
|
@@ -0,0 +1,26 @@
|
|
1
|
+
name: Code Quality
|
2
|
+
on: [ pull_request ]
|
3
|
+
jobs:
|
4
|
+
rubocop:
|
5
|
+
name: Rubocop
|
6
|
+
runs-on: ubuntu-latest
|
7
|
+
steps:
|
8
|
+
- name: Check out code
|
9
|
+
uses: actions/checkout@v2
|
10
|
+
- name: Install Ruby & Gems
|
11
|
+
uses: ruby/setup-ruby@v1 # Uses .ruby-version as version input
|
12
|
+
with:
|
13
|
+
ruby-version: 3.0
|
14
|
+
bundler-cache: true
|
15
|
+
- name: Rubocop
|
16
|
+
# https://github.com/reviewdog/action-rubocop
|
17
|
+
uses: reviewdog/action-rubocop@v2
|
18
|
+
with:
|
19
|
+
fail_on_error: true
|
20
|
+
filter_mode: nofilter
|
21
|
+
github_token: ${{ secrets.github_token }}
|
22
|
+
reporter: github-pr-review
|
23
|
+
rubocop_version: gemfile
|
24
|
+
# Rely on Bundler-installed gems so don't install them again
|
25
|
+
use_bundler: true
|
26
|
+
skip_install: true
|
data/.gitignore
CHANGED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require:
|
2
|
+
- rubocop-rspec
|
3
|
+
- rubocop-rake
|
4
|
+
- rubocop-performance
|
5
|
+
|
6
|
+
AllCops:
|
7
|
+
# We bump the version to get new cops, so enable them by default
|
8
|
+
NewCops: enable
|
9
|
+
|
10
|
+
# Two lines should fit next to each other in split view on a widescreen
|
11
|
+
Layout/LineLength:
|
12
|
+
Max: 120
|
13
|
+
|
14
|
+
# We still have old-style rspec checks, so this triggers on functional comparisons there
|
15
|
+
Lint/Void:
|
16
|
+
Exclude:
|
17
|
+
- 'spec/**/*_spec.rb'
|
18
|
+
|
19
|
+
# RSpec has a lot of blocks, so ignore this rule there
|
20
|
+
Metrics/BlockLength:
|
21
|
+
Exclude:
|
22
|
+
- 'spec/**/*_spec.rb'
|
23
|
+
|
24
|
+
# I prefer to see the class name over "described_class"
|
25
|
+
RSpec/DescribedClass:
|
26
|
+
EnforcedStyle: explicit
|
27
|
+
|
28
|
+
# I prefer groups for structure, so the defaults are a little too strict for me
|
29
|
+
RSpec/NestedGroups:
|
30
|
+
Max: 4
|
31
|
+
|
32
|
+
# I prefer more verbose examples, so tend to use more lines than the defaults
|
33
|
+
RSpec/ExampleLength:
|
34
|
+
Max: 20
|
35
|
+
|
36
|
+
# For strings I enjoy using %w[], but for symbols the %i[] syntax just does not click.
|
37
|
+
Style/SymbolArray:
|
38
|
+
EnforcedStyle: brackets
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
## Unreleased changes
|
2
|
+
|
3
|
+
## Version 0.4.0 -- 2021-09-07
|
4
|
+
|
5
|
+
Welcome to 2021, where Ruby version 2.6 is the lowest with official support, Bundler is the default for managing packages and RSpec version 3 is used to test things. This version updates Groupie into this decade.
|
6
|
+
|
7
|
+
- Refactor: update Groupie to 2021 standards
|
8
|
+
- Feat: raise Groupie::Error instead of RuntimeError
|
9
|
+
- Feat: deprecate String#tokenize in favor of Groupie.tokenize
|
10
|
+
- Doc: document API of Groupie
|
11
|
+
- Doc: update readme with examples
|
12
|
+
- Refactor: reorder Groupie methods by importance
|
13
|
+
- Refactor: simplify Groupie#classify
|
14
|
+
- Refactor: reduce complexity of Groupie#unique_words
|
15
|
+
- Refactor: simplify Groupie#classify\_text
|
16
|
+
|
17
|
+
## Version 0.3.0 -- 2010-07-29
|
18
|
+
|
19
|
+
Multiple changes to the 'unique words' strategy, hopefully improving the behavior.
|
20
|
+
|
21
|
+
- Cache unique words in an instance var to reduce time required to do subsequent lookups
|
22
|
+
- Sanity spec
|
23
|
+
- Unique strategy now includes all words except for the global 4th quartile
|
24
|
+
- Unique strategy changed yet again: only ignore words that occur more than their group's median
|
25
|
+
- Unique strategy now behaves like sqrt that only checks unique words
|
26
|
+
- Unique word finder uses less elegant but (hopefully) faster code
|
27
|
+
- Removed gemspec
|
28
|
+
|
29
|
+
## Version 0.2.3 -- 2010-07-29
|
30
|
+
|
31
|
+
Add a new 'unique words' strategy, which ignores words that occur in all categories.
|
32
|
+
|
33
|
+
- Added 'unique' classification strategy
|
34
|
+
- Added Group#<< as alias for Group#add
|
35
|
+
- Updated readme
|
36
|
+
|
37
|
+
## Version 0.2.2 -- 2010-07-25
|
38
|
+
|
39
|
+
Bugfix for log10 strategy.
|
40
|
+
|
41
|
+
- Fixed log10 strategy counting for Groupie.classify
|
42
|
+
|
43
|
+
## Version 0.2.1 -- 2010-07-25
|
44
|
+
|
45
|
+
Offer multiple ways to weigh word counts in calculating final scores.
|
46
|
+
|
47
|
+
- Added sqrt and log word counting strategies
|
48
|
+
|
49
|
+
## Version 0.2.0 -- 2010-07-25
|
50
|
+
|
51
|
+
Classification can't raise division by zero errors anymore.
|
52
|
+
|
53
|
+
- Groupie.classify_text ignores unclassified tokens
|
54
|
+
|
55
|
+
## Version 0.1.1 -- 2010-07-25
|
56
|
+
|
57
|
+
Swap test framework and tokenization improvements.
|
58
|
+
|
59
|
+
- Regenerated gemspec
|
60
|
+
- Strip quotes from tokens
|
61
|
+
- Replaced testy tests with rspec
|
62
|
+
|
63
|
+
## Version 0.1.0 -- 2010-07-25
|
64
|
+
|
65
|
+
The initial release as a gem, after working on this on/off over a year.
|
66
|
+
|
67
|
+
- Added gemspec
|
68
|
+
- Fixed text classification to properly average group scores
|
69
|
+
- Added test for classifying tokenized html email spam
|
70
|
+
- Classification of texts is now possible
|
71
|
+
- Added readme and MIT license
|
72
|
+
- Test the full html and headers of tokenized emails
|
73
|
+
- Support infix commas for tokenized strings
|
74
|
+
- Allow infix dots in tokenized strings
|
75
|
+
- Strip HTML tags when sanitizing a string
|
76
|
+
- Classify common words based on tokenized text from spam.la e-mails
|
77
|
+
- Added String#tokenize
|
78
|
+
- Ensure a Group will still work when loaded from YAML
|
79
|
+
- Added test helper file
|
80
|
+
- Refactored Group to maintain a Hash of words and counts instead of a list of words
|
81
|
+
- Removed obsolete method
|
82
|
+
- Added testcase for three groups
|
83
|
+
- Support multiple examples to add more weight to their grouping
|
84
|
+
- Renamed tests to reflect intent of content
|
85
|
+
- Classification now allows for a degree of certainty
|
86
|
+
- Implemented simple spam check
|
data/Gemfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
# Specify your gem's dependencies in groupie.gemspec
|
6
|
+
gemspec
|
7
|
+
|
8
|
+
gem 'rake', '~> 13.0'
|
9
|
+
gem 'rspec', '~> 3.0'
|
10
|
+
gem 'rubocop', '~> 1.7'
|
11
|
+
gem 'rubocop-performance', '~> 1.11'
|
12
|
+
gem 'rubocop-rake', '~> 0.6.0'
|
13
|
+
gem 'rubocop-rspec', '~> 2.4'
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
groupie (0.4.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
ast (2.4.2)
|
10
|
+
diff-lcs (1.4.4)
|
11
|
+
parallel (1.20.1)
|
12
|
+
parser (3.0.2.0)
|
13
|
+
ast (~> 2.4.1)
|
14
|
+
rainbow (3.0.0)
|
15
|
+
rake (13.0.6)
|
16
|
+
regexp_parser (2.1.1)
|
17
|
+
rexml (3.2.5)
|
18
|
+
rspec (3.10.0)
|
19
|
+
rspec-core (~> 3.10.0)
|
20
|
+
rspec-expectations (~> 3.10.0)
|
21
|
+
rspec-mocks (~> 3.10.0)
|
22
|
+
rspec-core (3.10.1)
|
23
|
+
rspec-support (~> 3.10.0)
|
24
|
+
rspec-expectations (3.10.1)
|
25
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
26
|
+
rspec-support (~> 3.10.0)
|
27
|
+
rspec-mocks (3.10.2)
|
28
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
29
|
+
rspec-support (~> 3.10.0)
|
30
|
+
rspec-support (3.10.2)
|
31
|
+
rubocop (1.20.0)
|
32
|
+
parallel (~> 1.10)
|
33
|
+
parser (>= 3.0.0.0)
|
34
|
+
rainbow (>= 2.2.2, < 4.0)
|
35
|
+
regexp_parser (>= 1.8, < 3.0)
|
36
|
+
rexml
|
37
|
+
rubocop-ast (>= 1.9.1, < 2.0)
|
38
|
+
ruby-progressbar (~> 1.7)
|
39
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
40
|
+
rubocop-ast (1.11.0)
|
41
|
+
parser (>= 3.0.1.1)
|
42
|
+
rubocop-performance (1.11.5)
|
43
|
+
rubocop (>= 1.7.0, < 2.0)
|
44
|
+
rubocop-ast (>= 0.4.0)
|
45
|
+
rubocop-rake (0.6.0)
|
46
|
+
rubocop (~> 1.0)
|
47
|
+
rubocop-rspec (2.4.0)
|
48
|
+
rubocop (~> 1.0)
|
49
|
+
rubocop-ast (>= 1.1.0)
|
50
|
+
ruby-progressbar (1.11.0)
|
51
|
+
unicode-display_width (2.0.0)
|
52
|
+
|
53
|
+
PLATFORMS
|
54
|
+
x86_64-darwin-20
|
55
|
+
x86_64-linux
|
56
|
+
|
57
|
+
DEPENDENCIES
|
58
|
+
groupie!
|
59
|
+
rake (~> 13.0)
|
60
|
+
rspec (~> 3.0)
|
61
|
+
rubocop (~> 1.7)
|
62
|
+
rubocop-performance (~> 1.11)
|
63
|
+
rubocop-rake (~> 0.6.0)
|
64
|
+
rubocop-rspec (~> 2.4)
|
65
|
+
|
66
|
+
BUNDLED WITH
|
67
|
+
2.2.24
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2009-2021 Wes Oldenbeuving
|
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,121 @@
|
|
1
|
+
# Groupie
|
2
|
+
|
3
|
+
Groupie is a simple way to group texts and classify new texts as being a likely member of one of the defined groups. Think of bayesian spam filters.
|
4
|
+
|
5
|
+
The eventual goal is to have Groupie work as a sort of bayesian spam filter, where you feed it spam and ham (non-spam) and ask it to classify new texts as spam or ham. Applications for this are e-mail spam filtering and blog spam filtering. Other sorts of categorizing might be interesting as well, such as finding suitable tags for a blog post or bookmark.
|
6
|
+
|
7
|
+
Started and forgotten in 2009 as a short-lived experiment, in 2010 Groupie got new features when I started using it on a RSS reader project that classified news items into "Interesting" and "Not interesting" categories.
|
8
|
+
|
9
|
+
## Current functionality
|
10
|
+
|
11
|
+
Current funcionality includes:
|
12
|
+
|
13
|
+
* Tokenize an input text to prepare it for grouping.
|
14
|
+
* Strip XML and HTML tag.
|
15
|
+
* Keep certain infix characters, such as period and comma.
|
16
|
+
* Add texts (as an Array of Strings) to any number of groups.
|
17
|
+
* Classify a single word to check the likelihood it belongs to each group.
|
18
|
+
* Do classification for complete (tokenized) texts.
|
19
|
+
* Pick classification strategy to weigh repeat words differently (weigh by sum, square root or log10 of words in group)
|
20
|
+
|
21
|
+
## Installation
|
22
|
+
|
23
|
+
Add this line to your application's Gemfile:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
gem 'groupie'
|
27
|
+
```
|
28
|
+
|
29
|
+
You can also perform this to do this for you:
|
30
|
+
|
31
|
+
bundle add groupie
|
32
|
+
|
33
|
+
And then execute:
|
34
|
+
|
35
|
+
bundle install
|
36
|
+
|
37
|
+
Or install it system-wide via:
|
38
|
+
|
39
|
+
gem install groupie
|
40
|
+
|
41
|
+
## Usage
|
42
|
+
|
43
|
+
Here is an annotated console session that shows off the features available in Groupie.
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
# Instantiate a new Groupie instance
|
47
|
+
groupie = Groupie.new
|
48
|
+
|
49
|
+
# Groups are defined as you use them, so let's get started by adding some pre-tokenized words
|
50
|
+
groupie[:spam].add(%w[this is obvious spam please buy our product])
|
51
|
+
groupie[:spam].add(%w[hello friend this is rich prince i have awesome bitcoin for you])
|
52
|
+
groupie[:ham].add(%w[you are invited to my awesome party just click the link to rsvp])
|
53
|
+
|
54
|
+
# Is your data less than clean? We've got a tokenizer for that!
|
55
|
+
tokens = Groupie.tokenize('Please give me your password so I can haxx0r you!')
|
56
|
+
# => ["please", "give", "me", "your", "password", "so", "i", "can", "haxx0r", "you"]
|
57
|
+
groupie[:spam].add(tokens)
|
58
|
+
|
59
|
+
# So, now let's attempt to classify a text and see if it's spam or ham:
|
60
|
+
test_tokens = %w[please click the link to reset your password for our awesome product]
|
61
|
+
groupie.classify_text(test_tokens)
|
62
|
+
# => {:spam=>0.5909090909090909, :ham=>0.4090909090909091}
|
63
|
+
# As you can see, this password reset email looks a little dodgy...
|
64
|
+
# We have multiple strategies for drawing conclusions about what group it belongs to.
|
65
|
+
# The default you saw above is :sum, it weighs each word by the total sum of occurrences.
|
66
|
+
# Let's see if it looks less bad by using a different classification strategies.
|
67
|
+
|
68
|
+
# Log reduces the weight of each word to the log10 of its occurrence count:
|
69
|
+
# - Count 1 is weight 0
|
70
|
+
# - Count 10 is weight 1
|
71
|
+
# - Count 100 is weight 2
|
72
|
+
groupie.classify_text(test_tokens, :log)
|
73
|
+
# => {:spam=>0.5, :ham=>0.5}
|
74
|
+
# This is even more even, most likely because it ignores all single-count words...
|
75
|
+
|
76
|
+
# Square root algorithm is less harsh, it reduces the weight of each word to the square root of the count:
|
77
|
+
# - Count 1 is weight 1
|
78
|
+
# - Count 4 is weight 2
|
79
|
+
# - Count 9 is weight 3
|
80
|
+
groupie.classify_text(test_tokens, :sqrt)
|
81
|
+
# => {:spam=>0.5909090909090909, :ham=>0.4090909090909091}
|
82
|
+
# This seems to result in the same value as :sum
|
83
|
+
|
84
|
+
# Unique uses the same weighting algorithm as the square root, but it modifies the word dictionary:
|
85
|
+
# it discards the 25% most common words, so less common words gain higher predictive power.
|
86
|
+
groupie.classify_text(test_tokens, :unique)
|
87
|
+
# => {:spam=>0.625, :ham=>0.375}
|
88
|
+
# This looks even worse for our poor password reset email.
|
89
|
+
# In case you're curious, the ignored words in this case are:
|
90
|
+
test_tokens - (test_tokens & groupie.unique_words)
|
91
|
+
# => ["please", "to", "reset", "awesome"]
|
92
|
+
# If you'd be classifying email, you can assume that common email headers will get ignored this way.
|
93
|
+
```
|
94
|
+
|
95
|
+
Persistence can be naively done by using YAML:
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
# Instantiate a new Groupie instance
|
99
|
+
groupie = Groupie.new
|
100
|
+
groupie[:spam].add(%w[assume you have a lot of data you care about])
|
101
|
+
|
102
|
+
require 'yaml'
|
103
|
+
yaml = YAML.dump(groupie)
|
104
|
+
loaded = YAML.safe_load(yaml, permitted_classes: [Groupie, Groupie::Group, Symbol])
|
105
|
+
```
|
106
|
+
|
107
|
+
For I'm still experimenting with Groupie in [Infinity Feed](https://www.infinity-feed.com), so persistence is a Future Problem for me there. In development, I'm building (low data count) classifiers in memory and discarding them after use.
|
108
|
+
|
109
|
+
## Development
|
110
|
+
|
111
|
+
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. Rubocop is available via `bin/rubocop` with some friendly default settings.
|
112
|
+
|
113
|
+
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 the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
114
|
+
|
115
|
+
## Contributing
|
116
|
+
|
117
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/Narnach/groupie.
|
118
|
+
|
119
|
+
## License
|
120
|
+
|
121
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|