crosby 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7b6644351cbd94255b116edf49999a4aa7f8a202
4
+ data.tar.gz: d206eadba0406bd3d0df0f7c07f7d819ec6eb38a
5
+ SHA512:
6
+ metadata.gz: 4a8bbab03e19b11417d517d44b76d7fa59c7a09d4d70fe35dc9ebb660538842d0ad8d431589b7296e0c431fb4575f174e314e16ffd46a41d91c82c393d3a6b90
7
+ data.tar.gz: 44460e785fa692c1249d98df48c912bd50a8b55f4fe6773d00c0dba1ddff5aeed78545110ffacf60c97af8995c47bd659d275010c34d847b4a2bd58ee7092e5d
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "pry"
4
+
5
+ # Specify your gem"s dependencies in crosby.gemspec
6
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Dan Matthews
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,211 @@
1
+ # Crosby
2
+
3
+ Allows for quality checks on `ActionMailer` emails when migrating to new systems.
4
+
5
+ http://en.wikipedia.org/wiki/Philip_B._Crosby
6
+
7
+ ```
8
+ Crosby's response to the quality crisis was the principle of
9
+ "doing it right the first time" (DIRFT). He also included four major principles:
10
+
11
+ The definition of quality is conformance to requirements
12
+ (requirements meaning both the product and the customer's requirements)
13
+ The system of quality is prevention
14
+ The performance standard is zero defects (relative to requirements)
15
+ The measurement of quality is the price of nonconformance
16
+ ```
17
+
18
+ This is a work in progress which came out of a need to compare emails generated
19
+ on our 'nextjenn' platform to emails generated in our legacy codebase.
20
+
21
+ ## Installation
22
+
23
+ Add this line to your application's Gemfile:
24
+
25
+ ```ruby
26
+ gem "crosby"
27
+ ```
28
+
29
+ And then execute:
30
+
31
+ $ bundle
32
+
33
+ Or install it yourself as:
34
+
35
+ $ gem install crosby
36
+
37
+ ## Configuration
38
+
39
+ Crosby has 2 configurable values, `app_name` and `export_path` with the
40
+ following defaults:
41
+
42
+ ```ruby
43
+ Crosby.config
44
+ # => { :app_name => "6f292f17", :export_path => "tmp/crosby" }
45
+ ```
46
+
47
+ NOTE: The value of `app_name` is randomized and will not stay consistent across
48
+ application loads unless specifically set. Config options can be set via a
49
+ block.
50
+
51
+ ```ruby
52
+ Crosby.config do |c|
53
+ c.app_name = "ExampleApp"
54
+ c.export_path = "../crosby_files"
55
+ end
56
+ ```
57
+
58
+ ## Usage
59
+
60
+ ### Basic Usage
61
+
62
+ Crosby exports a slightly curated version of `Mail::Message` objects produced
63
+ by `ActionMailer` subclasses to a `.crosby` file. The class responsible for
64
+ producing this file is `Crosby::Exporter`.
65
+
66
+ ```ruby
67
+ exporter = Crosby::Exporter.new(
68
+ MailerClass, :method, 'a-unique-id'[, arg1[, arg2[, ...]]]
69
+ )
70
+
71
+ exporter.export
72
+ ```
73
+
74
+ Also available is the `Crosby::Exporter#to_s` method which will return the
75
+ `.crosby` file's contents as a string.
76
+
77
+ ```ruby
78
+ exporter.to_s
79
+ ```
80
+
81
+ ### RSpec
82
+
83
+ `Crosby::RSpecHelper` works with RSpec 1, 2 & 3, and adds the `#crosby_email`
84
+ helper method. You can use this method to create `.crosby` files inside your
85
+ existing tests.
86
+
87
+ ```ruby
88
+ # spec_helper.rb
89
+
90
+ require "crosby/rspec_helper"
91
+
92
+ Crosby.config do |c|
93
+ # ...
94
+ end
95
+ ```
96
+
97
+ ```ruby
98
+ # spec/mailers/example_mailer_spec.rb
99
+ require "spec_helper"
100
+
101
+ describe ExampleMailer do
102
+ context "#notify" do
103
+ it "should send a notification email" do
104
+ mailer = ExampleMailer.notify(arg1, arg1)
105
+
106
+ # becomes
107
+ mailer = crosby_email(ExampleMailer, :notify, arg1, arg2)
108
+
109
+ # ...
110
+ end
111
+ end
112
+
113
+ # ...
114
+ end
115
+ ```
116
+
117
+ In the above example, Crosby will generate a uuid based on the mailer class,
118
+ method name and argument values. While this is fine, it may be helpful to
119
+ implicitly set the uuid. You can do this by setting the `@crosby_uuid` instance
120
+ variable in your test.
121
+
122
+ ```ruby
123
+ # spec/mailers/example_mailer_spec.rb
124
+ require "spec_helper"
125
+
126
+ describe ExampleMailer do
127
+ context "#notify" do
128
+ it "should send a notification email" do
129
+ @crosby_uuid = "example_mailer_notify"
130
+ mailer = crosby_email(ExampleMailer, :notify, arg1, arg2)
131
+
132
+ # ...
133
+ end
134
+ end
135
+
136
+ # ...
137
+ end
138
+ ```
139
+
140
+ ### Generating a diff
141
+
142
+ `Crosby::Diff` is responsible for comparing files of the same uuid to eachother.
143
+ There must be at least 2 files with the same uuid present in the configured
144
+ directory for a diff to be generated. If there are more than 2 files for a
145
+ given uuid, a diff will be generated for each unique pair of files.
146
+
147
+ ```ruby
148
+ Crosby::Diff.compare("example_mailer_notify")
149
+ # => [diff_str, ...]
150
+ ```
151
+
152
+ `Crosby::Diff.compare` returns an array of diff strings, one for each file pair.
153
+ When no pairs are present, `compare` returns an empty array.
154
+
155
+ ```ruby
156
+ Crosby::Diff.compare("not-an-existing-uuid")
157
+ # => []
158
+ ```
159
+
160
+ It also accepts an optional block, to be called once per diff string.
161
+
162
+ ```ruby
163
+ Crosby::Diff.compare("example_mailer_notify") { |diff| puts diff }
164
+ # diff output
165
+ # => [diff_str, ...]
166
+ ```
167
+
168
+ `Crosby::Diff.compare` and `Crosby::Diff.new` both accept an options hash to
169
+ override `Crosby.config` settings.
170
+
171
+ ```ruby
172
+ Crosby::Diff.compare("example_mailer_notify", :export_path => "../crosby_files")
173
+ Crosby::Diff.new("example_mailer_notify", :export_path => "../crosby_files")
174
+ ```
175
+
176
+ `Crosby::Diff` uses the excellent [Diffy gem](https://github.com/samg/diffy)
177
+ behind the scenes. If you would like access to the `Diffy::Diff` objects, you
178
+ can access them through the `Crosby::Diff#diffs` method.
179
+
180
+ ```ruby
181
+ cdiff = Crosby::Diff.new("example_mailer_notify")
182
+ cdiff.diffs
183
+ # => [ [#<Diffy::Diff:0x00000000>, #<Diffy::Diff:0x00000001], [..., ...], ... ]
184
+ ```
185
+
186
+ ### Rake
187
+
188
+ Crosby provides a simple `rake crosby:diff` command which outputs diffs for all
189
+ of the uuids represented by files in the directory specified at
190
+ `Crosby.config[:export_path]`.
191
+
192
+ ```ruby
193
+ # Rakefile
194
+ require "crosby/tasks"
195
+
196
+ Crosby.config do |c|
197
+ c.export_path = "../crosby_files"
198
+ end
199
+ ```
200
+
201
+ ```sh
202
+ bundle exec rake crosby:diff
203
+ ```
204
+
205
+ ## Contributing
206
+
207
+ 1. Fork it ( https://github.com/[my-github-username]/crosby/fork )
208
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
209
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
210
+ 4. Push to the branch (`git push origin my-new-feature`)
211
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ task :console do
4
+ require "crosby"
5
+ require "pry"
6
+ Pry.start
7
+ end
data/crosby.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "crosby/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "crosby"
8
+ spec.version = Crosby::VERSION
9
+ spec.authors = ["Dan Matthews"]
10
+ spec.email = ["dan.matthews@teamsnap.com"]
11
+ spec.summary = %q{Quality Assurance for ActionMailer}
12
+ spec.description = %q{Allows generation and comparison of email output}
13
+ spec.homepage = "https://github.com/teamsnap/crosby"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+
24
+ spec.add_dependency "diffy", "~> 3.0"
25
+ spec.add_dependency "nokogiri", "~> 1.6"
26
+ end
@@ -0,0 +1,25 @@
1
+ require "securerandom"
2
+
3
+ module Crosby
4
+ class Configuration
5
+ attr_accessor :app_name, :export_path
6
+
7
+ def initialize
8
+ self.app_name = SecureRandom.hex(4)
9
+ self.export_path = "tmp/crosby"
10
+ end
11
+
12
+ def config(&block)
13
+ block.call(self) if block_given?
14
+ to_hsh
15
+ end
16
+
17
+ def to_hsh
18
+ {
19
+ :app_name => app_name,
20
+ :export_path => export_path
21
+ }
22
+ end
23
+ alias :to_h :to_hsh
24
+ end
25
+ end
@@ -0,0 +1,81 @@
1
+ require "diffy"
2
+
3
+ module Crosby
4
+ class Diff
5
+ class << self
6
+ def compare(uuid, options = {}, &block)
7
+ new(uuid, options).compare(&block)
8
+ end
9
+ end
10
+
11
+ def initialize(uuid, options = {})
12
+ @uuid = uuid
13
+ @config = Crosby.config.merge(options)
14
+ end
15
+
16
+ # https://github.com/samg/diffy#supported-formats
17
+ def compare(format = :color, &block)
18
+ diffs.map { |diff|
19
+ out = diff.to_s(format)
20
+ block_given? ? block.call(out) : out
21
+ }
22
+ end
23
+
24
+ def diffs
25
+ @diffs ||= [].tap { |diffs|
26
+ pairs.each { |pair|
27
+ diffs << Diffy::Diff.new(
28
+ *pair,
29
+ :context => 0,
30
+ :include_diff_info => true,
31
+ :source => "files"
32
+ )
33
+ }
34
+ }
35
+ end
36
+
37
+ private
38
+
39
+ def build_file_paths(pairs)
40
+ pairs.map { |pair|
41
+ pair.map { |filename|
42
+ File.realpath(File.join(@config[:export_path], filename))
43
+ }
44
+ }
45
+ end
46
+
47
+ def files
48
+ matcher = Regexp.new("#{@uuid}\\.crosby\\z")
49
+
50
+ Dir.new(@config[:export_path]).entries.select { |entry|
51
+ entry =~ matcher ? true : false
52
+ }
53
+ end
54
+
55
+ def pairs
56
+ [
57
+ :unique_pairs,
58
+ :sort_pairs,
59
+ :build_file_paths
60
+ ].reduce([]) { |obj, meth|
61
+ send(meth, obj)
62
+ }
63
+ end
64
+
65
+ def sort_pairs(pairs)
66
+ pairs.map { |pair|
67
+ pair.first =~ Regexp.new(@config[:app_name]) ? pair.reverse : pair
68
+ }
69
+ end
70
+
71
+ def unique_pairs(arr)
72
+ arr.tap { |pairs|
73
+ files.repeated_permutation(2) { |permutation|
74
+ pairs << permutation.sort unless permutation.uniq.length == 1
75
+ }
76
+
77
+ pairs.uniq!
78
+ }
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,5 @@
1
+ module Crosby
2
+ MissingDependency = Class.new(StandardError)
3
+ MissingRSpec = Class.new(StandardError)
4
+ UnsupportedVersion = Class.new(StandardError)
5
+ end
@@ -0,0 +1,108 @@
1
+ require "fileutils"
2
+ require "securerandom"
3
+ require "nokogiri"
4
+
5
+ module Crosby
6
+ class Exporter
7
+ WRITE_MODE = "w"
8
+
9
+ attr_reader :mail
10
+
11
+ def initialize(mailer, method, uuid = SecureRandom.hex(8), *args)
12
+ @args = args
13
+ @mailer = mailer
14
+ @method = method
15
+ @uuid = uuid
16
+ @version = Crosby.action_mailer_version
17
+
18
+ config = Crosby.config
19
+ @path = config[:export_path]
20
+ @app_name = config[:app_name]
21
+ end
22
+
23
+ def export
24
+ ensure_path_exists
25
+ write
26
+ true
27
+ end
28
+
29
+ def to_s
30
+ create_mail unless mail
31
+
32
+ [
33
+ "TO: #{mail.to}",
34
+ "CC: #{mail.cc}",
35
+ "BCC: #{mail.bcc}",
36
+ "REPLY TO: #{mail.reply_to}",
37
+ "FROM: #{mail.from}",
38
+ "HTML:",
39
+ commonize_html(mail.html_part.body.raw_source),
40
+ "TEXT:",
41
+ commonize_text(mail.text_part.body.raw_source)
42
+ ].join("\n")
43
+ end
44
+
45
+ private
46
+
47
+ def commonize_html(str)
48
+ commonize_text(str)
49
+ compact(Nokogiri::HTML::Document.parse(commonize_text(str)).to_s)
50
+ end
51
+
52
+ def commonize_text(str)
53
+ str
54
+ .gsub(/([^=])=\n/, '\1') # single quotes required for encoding
55
+ .gsub(/=3D/, "=")
56
+ end
57
+
58
+ def compact(str)
59
+ str
60
+ .each_line
61
+ .reject(&:blank?)
62
+ .map{ |line|
63
+ line
64
+ .gsub(/\s+/, " ")
65
+ .gsub(/^ /, "")
66
+ .gsub(/ $/, "\n")
67
+ .gsub(/></, ">\n<")
68
+ }
69
+ .join
70
+ end
71
+
72
+ def create_mail
73
+ method = @method
74
+
75
+ case @version::MAJOR
76
+ when 2
77
+ method = "create_#{method}"
78
+ when 3
79
+ # supported, no additional action required
80
+ when 4
81
+ # supported, no additional action required
82
+ else
83
+ raise Crosby::UnsupportedVersion, "We do not yet support version " \
84
+ "#{@version::STRING} of ActionMailer"
85
+ end
86
+
87
+ @mail = @mailer.send(method, *@args)
88
+ end
89
+
90
+ def ensure_path_exists
91
+ @dir = Dir.new(FileUtils.mkdir_p(@path).first)
92
+ end
93
+
94
+ def file(&block)
95
+ File.open(filename, WRITE_MODE, &block)
96
+ end
97
+
98
+ def filename
99
+ File.join(@dir, "#{@mailer.name}.#{@method}.#{@app_name}.#{@uuid}.crosby")
100
+ end
101
+
102
+ def write
103
+ file do |f|
104
+ f.write(to_s)
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,31 @@
1
+ require "base64"
2
+ require "crosby"
3
+
4
+ module Crosby
5
+ module RSpecHelper
6
+ def crosby_email(mailer, method, *args)
7
+ @crosby_uuid ||= generate_crosby_digest(mailer, method, *args)
8
+ exporter = Crosby::Exporter.new(mailer, method, @crosby_uuid, *args)
9
+ return (exporter.export ? exporter.mail : false)
10
+ end
11
+
12
+ def generate_crosby_digest(*args)
13
+ Base64.encode64(args.map(&:to_s).join("|")).chomp
14
+ end
15
+ end
16
+ end
17
+
18
+ begin
19
+ if Kernel.const_defined?(:Spec)
20
+ class ActiveSupport::TestCase
21
+ include Crosby::RSpecHelper
22
+ end
23
+ else
24
+ RSpec.configure do |c|
25
+ c.include Crosby::RSpecHelper
26
+ end
27
+ end
28
+ rescue NameError
29
+ raise Crosby::MissingRSpec, "Crosby can't find RSpec at the Spec::Runner " \
30
+ "or RSpec namespace."
31
+ end
@@ -0,0 +1,44 @@
1
+ require "crosby"
2
+
3
+ module Crosby
4
+ class Tasks
5
+ include Rake::DSL if defined? Rake::DSL
6
+
7
+ def install_tasks
8
+ namespace :crosby do
9
+ desc "displays all diffs in the configured folder " +
10
+ "(#{Crosby.config[:export_path]})"
11
+ task :diff do
12
+ each_uuid do |uuid|
13
+ puts "============================================================"
14
+ puts "UUID: #{uuid}"
15
+ puts "============================================================"
16
+ Crosby::Diff.compare(uuid) { |diff| puts diff }
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def each_uuid(&block)
25
+ [].tap { |uuids|
26
+ Dir.new(Crosby.config[:export_path]).each { |filename|
27
+ uuids << extract_uuid(filename) if filename =~ /\.crosby$/
28
+ }
29
+
30
+ uuids.compact!
31
+ uuids.uniq!
32
+ uuids.sort!
33
+
34
+ uuids.each { |uuid| block.call(uuid) } if block_given?
35
+ }
36
+ end
37
+
38
+ def extract_uuid(filename)
39
+ filename.gsub(/^.+\..+\..+\.(\S+)\.crosby$/, '\1')
40
+ end
41
+ end
42
+ end
43
+
44
+ Crosby::Tasks.new.install_tasks
@@ -0,0 +1,3 @@
1
+ module Crosby
2
+ VERSION = "0.1.0"
3
+ end
data/lib/crosby.rb ADDED
@@ -0,0 +1,20 @@
1
+ require "crosby/version"
2
+
3
+ module Crosby
4
+ def self.config(&block)
5
+ @@configuration ||= Configuration.new
6
+ @@configuration.config(&block)
7
+ end
8
+
9
+ def self.action_mailer_version
10
+ require "action_mailer/version"
11
+ ActionMailer::VERSION
12
+ rescue
13
+ raise Crosby::MissingDependency, "Some version of ActionMailer is required"
14
+ end
15
+ end
16
+
17
+ require "crosby/configuration"
18
+ require "crosby/errors"
19
+ require "crosby/exporter"
20
+ require "crosby/diff"
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: crosby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Dan Matthews
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: diffy
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: nokogiri
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.6'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.6'
69
+ description: Allows generation and comparison of email output
70
+ email:
71
+ - dan.matthews@teamsnap.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - Gemfile
78
+ - LICENSE.txt
79
+ - README.md
80
+ - Rakefile
81
+ - crosby.gemspec
82
+ - lib/crosby.rb
83
+ - lib/crosby/configuration.rb
84
+ - lib/crosby/diff.rb
85
+ - lib/crosby/errors.rb
86
+ - lib/crosby/exporter.rb
87
+ - lib/crosby/rspec_helper.rb
88
+ - lib/crosby/tasks.rb
89
+ - lib/crosby/version.rb
90
+ homepage: https://github.com/teamsnap/crosby
91
+ licenses:
92
+ - MIT
93
+ metadata: {}
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 2.2.2
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: Quality Assurance for ActionMailer
114
+ test_files: []