sweet_notifications 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 +7 -0
- data/.gitignore +22 -0
- data/.rubocop.yml +19 -0
- data/.travis.yml +12 -0
- data/Appraisals +7 -0
- data/CONTRIBUTING.md +20 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +85 -0
- data/Rakefile +18 -0
- data/gemfiles/rails_4.0.gemfile +7 -0
- data/gemfiles/rails_4.1.gemfile +7 -0
- data/lib/sweet_notifications/controller_runtime.rb +52 -0
- data/lib/sweet_notifications/log_subscriber.rb +81 -0
- data/lib/sweet_notifications/railtie.rb +36 -0
- data/lib/sweet_notifications/version.rb +3 -0
- data/lib/sweet_notifications.rb +42 -0
- data/sweet_notifications.gemspec +34 -0
- data/test/controller_runtime_test.rb +88 -0
- data/test/log_subscriber_test.rb +150 -0
- data/test/railtie_test.rb +32 -0
- data/test/sweet_notifications_test.rb +60 -0
- data/test/test_helper.rb +42 -0
- metadata +227 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1c1adad5429dc0a8d3ec40a499531b9fabacc9b5
|
4
|
+
data.tar.gz: 360d747cf1d39ac6bfc3c9583e87adcf110d0f03
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1e20abf7323c1ccc38984ff3b03105503c8e1e96025d54c3cb0ea23d8de015164923a6c8076f1bbc649b4f1d365bc167a3687a4dc92f96ee2b6724805d8ffd1a
|
7
|
+
data.tar.gz: 2019786e91f894fbb984e351f1d996da0f8b78c3b694026ba8aacee5d213fd50a14a6e541d2416372fb29a345816801383c060065943fe6905c892506a86190d
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
*emfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
AllCops:
|
2
|
+
Exclude:
|
3
|
+
- sweet_notifications.gemspec
|
4
|
+
- lib/sweet_notifications/version.rb
|
5
|
+
|
6
|
+
ClassAndModuleChildren:
|
7
|
+
Exclude:
|
8
|
+
- test/**/*.rb
|
9
|
+
|
10
|
+
Documentation:
|
11
|
+
Include:
|
12
|
+
- lib/**/*.rb
|
13
|
+
|
14
|
+
MethodLength:
|
15
|
+
Exclude:
|
16
|
+
- lib/sweet_notifications/controller_runtime.rb
|
17
|
+
|
18
|
+
ModuleFunction:
|
19
|
+
Enabled: false
|
data/.travis.yml
ADDED
data/Appraisals
ADDED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
## Contributing
|
2
|
+
|
3
|
+
Any contributions to SweetNotifications are welcome, whether they are feedback,
|
4
|
+
bug reports, or - even better - pull requests.
|
5
|
+
|
6
|
+
## Submitting a Pull Request
|
7
|
+
1. [Fork the repository.][fork]
|
8
|
+
2. [Create a topic branch.][branch]
|
9
|
+
3. Add specs for your unimplemented feature or bug fix.
|
10
|
+
4. Run `bundle exec rake test`. If your specs pass, return to step 3.
|
11
|
+
5. Implement your feature or bug fix.
|
12
|
+
6. Run `bundle exec rake default`. If your specs fail, return to step 5.
|
13
|
+
7. Run `open coverage/index.html`. If your changes are not completely covered
|
14
|
+
by your tests, return to step 3.
|
15
|
+
8. Add, commit, and push your changes.
|
16
|
+
9. [Submit a pull request.][pr]
|
17
|
+
|
18
|
+
[fork]: http://help.github.com/fork-a-repo/
|
19
|
+
[branch]: http://learn.github.com/p/branching.html
|
20
|
+
[pr]: http://help.github.com/send-pull-requests/
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Ville Lautanala
|
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,85 @@
|
|
1
|
+
# SweetNotifications [](https://travis-ci.org/lautis/sweet_notifications)
|
2
|
+
|
3
|
+
Syntactic sugar for ActiveSupport::LogSubscriber for easy instrumentation and
|
4
|
+
logging from third-party libraries.
|
5
|
+
|
6
|
+
This gem currently requires Ruby 2.0 or JRuby in 2.0 mode.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your Rails application's Gemfile:
|
11
|
+
|
12
|
+
gem 'sweet_notifications'
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install sweet_notifications
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
This library helps with creating ActiveSupport::Notifications subscribers for
|
25
|
+
logging purposes. First, there should be a source of notifications:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
|
29
|
+
class CandiesController < ApplicationController
|
30
|
+
def index
|
31
|
+
candies = %w{M&M's Gummibears Pez Salmiakki}
|
32
|
+
ActiveSupport::Notifications.instrument 'list.candies', list: candies do
|
33
|
+
sleep 0.5
|
34
|
+
render json: candies
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
Then, subscribe to these notifications using SweetNotifications in an initializer:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
SweetNotifications.subscribe :candies do
|
44
|
+
color ActiveSupport::LogSubscriber::GREEN
|
45
|
+
event :list, runtime: true do |event|
|
46
|
+
return unless logger.debug?
|
47
|
+
debug message(event, 'Candy', "listing candies: #{event.payload[:candies]}")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
`SweetNotifications.subscribe` will subscribe to the namespace given as
|
53
|
+
argument and, if necessary, create a Rails initializer that will be run when
|
54
|
+
the application is initialized.
|
55
|
+
|
56
|
+
If this functionality is too much, use `SweetNotification::LogSubscriber` to
|
57
|
+
create LogSusbcribers and `SweetNotification.controller_runtime` to bind this
|
58
|
+
to the Rails controller logging runtime logging functionality.
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
class AwesomeLogSubscriber < SweetNotifications::LogSubscriber
|
62
|
+
color ActiveSupport::LogSubscriber::CYAN, ActiveSupport::LogSubscriber::MAGENTA
|
63
|
+
event :cool, runtime: true do |event|
|
64
|
+
info "Cool stuff"
|
65
|
+
end
|
66
|
+
|
67
|
+
event :insanely_great, runtime: false do |event|
|
68
|
+
debug "Insanely greate"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
AwesomeLogSubscriber.attach_to :namespace
|
73
|
+
ControllerRuntime = SweetNotifications.controller_runtime(:namespace, AwesomeLogSubscriber)
|
74
|
+
|
75
|
+
ActionController::Base.send(:include, ControllerRuntime)
|
76
|
+
|
77
|
+
```
|
78
|
+
|
79
|
+
## Contributing
|
80
|
+
|
81
|
+
See [CONTRIBUTING.md](https://raw.githubusercontent.com/lautis/sweet_notifications/master/CONTRIBUTING.md).
|
82
|
+
|
83
|
+
## Copyright
|
84
|
+
|
85
|
+
Copyright 2014 Ville Lautanala. Released under [the MIT license](https://github.com/lautis/uglifier/blob/master/LICENSE.txt).
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rubocop/rake_task'
|
4
|
+
require 'yard'
|
5
|
+
|
6
|
+
Rake::TestTask.new do |t|
|
7
|
+
t.libs << 'test'
|
8
|
+
t.pattern = 'test/*_test.rb'
|
9
|
+
end
|
10
|
+
|
11
|
+
YARD::Rake::YardocTask.new do |t|
|
12
|
+
t.files = ['lib/**/*.rb']
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Check for code style'
|
16
|
+
Rubocop::RakeTask.new
|
17
|
+
|
18
|
+
task default: [:test, :rubocop]
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
require 'active_support/core_ext/module/attr_internal'
|
3
|
+
|
4
|
+
module SweetNotifications
|
5
|
+
# Controller runtime tracking
|
6
|
+
module ControllerRuntime
|
7
|
+
# Define a controller runtime logger for a LogSusbcriber
|
8
|
+
#
|
9
|
+
# @param name [String] title for logging
|
10
|
+
# @return [Module] controller runtime tracking mixin
|
11
|
+
def controller_runtime(name, log_subscriber)
|
12
|
+
runtime_attr = "#{name.to_s.underscore}_runtime".to_sym
|
13
|
+
Module.new do
|
14
|
+
extend ActiveSupport::Concern
|
15
|
+
attr_internal runtime_attr
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
define_method :process_action do |action, *args|
|
20
|
+
log_subscriber.reset_runtime
|
21
|
+
super(action, *args)
|
22
|
+
end
|
23
|
+
|
24
|
+
define_method :cleanup_view_runtime do |&block|
|
25
|
+
runtime_before_render = log_subscriber.reset_runtime
|
26
|
+
send("#{runtime_attr}=",
|
27
|
+
(send(runtime_attr) || 0) + runtime_before_render)
|
28
|
+
runtime = super(&block)
|
29
|
+
runtime_after_render = log_subscriber.reset_runtime
|
30
|
+
send("#{runtime_attr}=", send(runtime_attr) + runtime_after_render)
|
31
|
+
runtime - runtime_after_render
|
32
|
+
end
|
33
|
+
|
34
|
+
define_method :append_info_to_payload do |payload|
|
35
|
+
super(payload)
|
36
|
+
runtime = (send(runtime_attr) || 0) + log_subscriber.reset_runtime
|
37
|
+
payload[runtime_attr] = runtime
|
38
|
+
end
|
39
|
+
|
40
|
+
const_set(:ClassMethods, Module.new do
|
41
|
+
define_method :log_process_action do |payload|
|
42
|
+
messages, runtime = super(payload), payload[runtime_attr]
|
43
|
+
if runtime && runtime != 0
|
44
|
+
messages << format("#{name}: %.1fms", runtime.to_f)
|
45
|
+
end
|
46
|
+
messages
|
47
|
+
end
|
48
|
+
end)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'active_support/log_subscriber'
|
2
|
+
require 'request_store'
|
3
|
+
require 'securerandom'
|
4
|
+
|
5
|
+
module SweetNotifications
|
6
|
+
# LogSubscriber with runtime calculation and improved logging
|
7
|
+
class LogSubscriber < ActiveSupport::LogSubscriber
|
8
|
+
class_attribute :odd_color, :even_color
|
9
|
+
|
10
|
+
# Format a message for logging
|
11
|
+
#
|
12
|
+
# @param event [ActiveSupport::Notifications::Event] subscribed event
|
13
|
+
# @param label [String] label for log messages
|
14
|
+
# @param body [String] the rest
|
15
|
+
# @return [String] formatted message for logging
|
16
|
+
#
|
17
|
+
# ==== Examples
|
18
|
+
#
|
19
|
+
# event :test do |event|
|
20
|
+
# message(event, 'Test', 'message body')
|
21
|
+
# end
|
22
|
+
# # => " Test (0.00ms) message body"
|
23
|
+
def message(event, label, body)
|
24
|
+
@odd = !@odd
|
25
|
+
label_color = @odd ? odd_color : even_color
|
26
|
+
|
27
|
+
format(
|
28
|
+
' %s (%.2fms) %s',
|
29
|
+
color(label, label_color, true),
|
30
|
+
event.duration,
|
31
|
+
color(body, nil, !@odd)
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
class << self
|
36
|
+
# Store aggregated runtime form request specific store
|
37
|
+
def runtime=(value)
|
38
|
+
RequestStore.store["#{@name}_runtime"] = value
|
39
|
+
end
|
40
|
+
|
41
|
+
# Fetch aggregated runtime form request specific store
|
42
|
+
def runtime
|
43
|
+
RequestStore.store["#{@name}_runtime"] || 0
|
44
|
+
end
|
45
|
+
|
46
|
+
# Reset aggregated runtime
|
47
|
+
#
|
48
|
+
# @return Numeric previous runtime value
|
49
|
+
def reset_runtime
|
50
|
+
rt, self.runtime = runtime, 0
|
51
|
+
rt
|
52
|
+
end
|
53
|
+
|
54
|
+
# Set colors for logging title and duration
|
55
|
+
def color(odd, even = nil)
|
56
|
+
self.odd_color = odd
|
57
|
+
self.even_color = even || odd
|
58
|
+
end
|
59
|
+
|
60
|
+
# Define an event subscriber
|
61
|
+
#
|
62
|
+
# @param command [Symbol] event name
|
63
|
+
# @param runtime [Boolean] aggregate runtime for this event
|
64
|
+
# @yield [ActiveSupport::Notifications::Event] handle event
|
65
|
+
def event(command, runtime: true, &block)
|
66
|
+
define_method command do |event|
|
67
|
+
self.class.runtime += event.duration if runtime
|
68
|
+
instance_exec(event, &block) if block
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
protected
|
73
|
+
|
74
|
+
def inherited(base)
|
75
|
+
base.class_eval do
|
76
|
+
@name ||= SecureRandom.hex
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'rails/railtie'
|
2
|
+
|
3
|
+
module SweetNotifications
|
4
|
+
# Rails Railtie integration
|
5
|
+
module Railtie
|
6
|
+
extend self
|
7
|
+
# Attach LogSubscriber and ControllerRuntime to a notifications namespace
|
8
|
+
#
|
9
|
+
# @param name [Symbol] Notifications namespace
|
10
|
+
# @param log_subscriber [LogSubscriber] subscriber to be attached
|
11
|
+
# @param controller_runtime [Module] mixin that logs runtime
|
12
|
+
def initialize_rails(name, log_subscriber, controller_runtime)
|
13
|
+
log_subscriber.attach_to name.to_sym
|
14
|
+
ActiveSupport.on_load(:action_controller) do
|
15
|
+
include controller_runtime
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Create a Railtie for LogSubscriber and ControllerRuntime mixin
|
20
|
+
#
|
21
|
+
# @param name [Symbol] Notifications namespace
|
22
|
+
# @param log_subscriber [LogSubscriber] subscriber to be attached
|
23
|
+
# @param controller_runtime [Module] mixin that logs runtime
|
24
|
+
# @return [Rails::Railtie] Rails initializer
|
25
|
+
def railtie(name, log_subscriber, controller_runtime)
|
26
|
+
Class.new(Rails::Railtie) do
|
27
|
+
railtie_name name
|
28
|
+
initializer "#{name}.notifications" do
|
29
|
+
SweetNotifications::Railtie.initialize_rails(name,
|
30
|
+
log_subscriber,
|
31
|
+
controller_runtime)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'sweet_notifications/version'
|
2
|
+
require 'sweet_notifications/log_subscriber'
|
3
|
+
require 'sweet_notifications/controller_runtime'
|
4
|
+
require 'sweet_notifications/railtie'
|
5
|
+
|
6
|
+
# Syntactic sugar for ActiveSupport::Notifications subscribers for logging
|
7
|
+
# purposes in Rails.
|
8
|
+
module SweetNotifications
|
9
|
+
extend ControllerRuntime
|
10
|
+
extend Railtie
|
11
|
+
|
12
|
+
# Subscribe to an ActiveSupport::Notifications namespace.
|
13
|
+
#
|
14
|
+
# This will subscribe to the namespace given as argument and, if necessary,
|
15
|
+
# create a Rails initializer that will be run when the application is
|
16
|
+
# initialized.
|
17
|
+
#
|
18
|
+
# @param name [Symbol] event namespace
|
19
|
+
# @return [Rails::Railtie, ActiveSupport::LogSubscriber] An array consisting
|
20
|
+
# of a Railtie and a LogSubscriber
|
21
|
+
# @yield event subscription
|
22
|
+
#
|
23
|
+
# ==== Examples
|
24
|
+
#
|
25
|
+
# SweetNotifications.subscribe :active_record do
|
26
|
+
# color ActiveSupport::LogSubscriber::GREEN
|
27
|
+
# event :sql, runtime: true do |event|
|
28
|
+
# return unless logger.debug?
|
29
|
+
# debug message(event, event.payload[:name], event.payload[:sql])
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
def self.subscribe(name, &block)
|
33
|
+
log_subscriber = Class.new(SweetNotifications::LogSubscriber, &block)
|
34
|
+
controller_runtime = self.controller_runtime(name, log_subscriber)
|
35
|
+
if Rails.try(:application).try(:initialized?)
|
36
|
+
initialize_rails(name, log_subscriber, controller_runtime)
|
37
|
+
[nil, log_subscriber]
|
38
|
+
else
|
39
|
+
[railtie(name, log_subscriber, controller_runtime), log_subscriber]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'sweet_notifications/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "sweet_notifications"
|
8
|
+
spec.version = SweetNotifications::VERSION
|
9
|
+
spec.authors = ["Ville Lautanala"]
|
10
|
+
spec.email = ["lautis@gmail.com"]
|
11
|
+
spec.summary = %q{Syntactic sugar for ActiveSupport::LogSubscriber.}
|
12
|
+
spec.description = %q{Syntactic sugar for ActiveSupport::LogSubscriber for easy instrumentation and logging from third-party libraries.}
|
13
|
+
spec.homepage = "https://github.com/lautis/sweet_notifications"
|
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.required_ruby_version = '~> 2.0'
|
22
|
+
|
23
|
+
spec.add_runtime_dependency "activesupport", "~> 4.0"
|
24
|
+
spec.add_runtime_dependency "request_store", "~> 1.0"
|
25
|
+
spec.add_runtime_dependency "railties", "~> 4.0"
|
26
|
+
spec.add_development_dependency "actionpack", "~> 4.0"
|
27
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
28
|
+
spec.add_development_dependency "minitest"
|
29
|
+
spec.add_development_dependency "rake", "~> 10.3"
|
30
|
+
spec.add_development_dependency "yard", "~> 0.8.7"
|
31
|
+
spec.add_development_dependency "appraisal", "~> 1.0"
|
32
|
+
spec.add_development_dependency "simplecov", "~> 0.8.2"
|
33
|
+
spec.add_development_dependency "rubocop", "~> 0.22.0"
|
34
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'active_support/test_case'
|
2
|
+
require 'active_support/log_subscriber'
|
3
|
+
require 'active_support/log_subscriber/test_helper'
|
4
|
+
require 'action_controller/log_subscriber'
|
5
|
+
require 'action_controller'
|
6
|
+
require 'test_helper'
|
7
|
+
|
8
|
+
describe SweetNotifications::ControllerRuntime do
|
9
|
+
class TestLogSubscriber < SweetNotifications::LogSubscriber
|
10
|
+
end
|
11
|
+
|
12
|
+
ControllerRuntime = SweetNotifications.controller_runtime('Test',
|
13
|
+
TestLogSubscriber)
|
14
|
+
ActionController::Base.send :include, ControllerRuntime
|
15
|
+
|
16
|
+
class LogSubscribersController < ActionController::Base
|
17
|
+
def create
|
18
|
+
TestLogSubscriber.runtime += 100
|
19
|
+
render text: '100'
|
20
|
+
end
|
21
|
+
|
22
|
+
def show
|
23
|
+
render text: '0'
|
24
|
+
end
|
25
|
+
|
26
|
+
def destroy
|
27
|
+
TestLogSubscriber.runtime += 50
|
28
|
+
render text: 'OK'
|
29
|
+
TestLogSubscriber.runtime += 5
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
include ActiveSupport::LogSubscriber::TestHelper
|
34
|
+
tests LogSubscribersController
|
35
|
+
|
36
|
+
before do
|
37
|
+
@old_logger = ActionController::Base.logger
|
38
|
+
ActionController::LogSubscriber.attach_to :action_controller
|
39
|
+
end
|
40
|
+
|
41
|
+
after do
|
42
|
+
ActiveSupport::LogSubscriber.log_subscribers.clear
|
43
|
+
ActionController::Base.logger = @old_logger
|
44
|
+
end
|
45
|
+
|
46
|
+
# rubocop:disable AccessorMethodName
|
47
|
+
def set_logger(logger)
|
48
|
+
ActionController::Base.logger = logger
|
49
|
+
end
|
50
|
+
# rubocop:enable AccessorMethodName
|
51
|
+
|
52
|
+
describe '.log_process_action' do
|
53
|
+
it 'emits runtime to log messages' do
|
54
|
+
out = LogSubscribersController.log_process_action(test_runtime: 1234)
|
55
|
+
assert_equal('Test: 1234.0ms', out[0])
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'runtime logging' do
|
60
|
+
it 'does not append runtime when it is 0' do
|
61
|
+
get :show, id: 1
|
62
|
+
wait
|
63
|
+
assert_no_match(/Test:/, @logger.logged(:info)[2])
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'appends non-zero runtime' do
|
67
|
+
post :create, test: 1
|
68
|
+
wait
|
69
|
+
expected_message = /\(Views: [\d.]+ms \| Test: 100.0ms\)/
|
70
|
+
assert_match(expected_message, @logger.logged(:info)[2])
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'resets runtime before request' do
|
74
|
+
TestLogSubscriber.runtime += 1000
|
75
|
+
post :create, test: 1
|
76
|
+
wait
|
77
|
+
expected_message = /\(Views: [\d.]+ms \| Test: 100.0ms\)/
|
78
|
+
assert_match(expected_message, @logger.logged(:info)[2])
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'includes runtime after render' do
|
82
|
+
post :destroy, id: 1
|
83
|
+
wait
|
84
|
+
expected_message = /\(Views: [\d.]+ms \| Test: 55.0ms\)/
|
85
|
+
assert_match(expected_message, @logger.logged(:info)[2])
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'active_support/log_subscriber/test_helper'
|
3
|
+
|
4
|
+
describe SweetNotifications::LogSubscriber do
|
5
|
+
include ActiveSupport::LogSubscriber::TestHelper
|
6
|
+
|
7
|
+
def event(name: 'Test', duration: 1, transaction_id: SecureRandom.hex,
|
8
|
+
payload: {})
|
9
|
+
now = Time.now
|
10
|
+
ActiveSupport::Notifications::Event.new(name,
|
11
|
+
now,
|
12
|
+
now + duration,
|
13
|
+
transaction_id,
|
14
|
+
payload)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '.event' do
|
18
|
+
it 'creates event listener for event' do
|
19
|
+
class LogSubscriber < SweetNotifications::LogSubscriber
|
20
|
+
event :test
|
21
|
+
end
|
22
|
+
assert LogSubscriber.new.respond_to?(:test)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'proxies messages to Rails logger' do
|
26
|
+
class LoggingLogSubscriber < SweetNotifications::LogSubscriber
|
27
|
+
event :test_event do
|
28
|
+
debug 'test, 1-2-3'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
log_subscriber = LoggingLogSubscriber.new
|
32
|
+
log_subscriber.test_event(event)
|
33
|
+
assert_equal ['test, 1-2-3'], @logger.logged(:debug)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'increments runtime when asked to' do
|
37
|
+
class RuntimeLogSubscriber < SweetNotifications::LogSubscriber
|
38
|
+
event :runtime_event, runtime: true
|
39
|
+
event :no_runtime_event, runtime: false
|
40
|
+
end
|
41
|
+
|
42
|
+
log_subscriber = RuntimeLogSubscriber.new
|
43
|
+
log_subscriber.runtime_event(event(duration: 5))
|
44
|
+
assert_equal 5000.0, RuntimeLogSubscriber.runtime
|
45
|
+
log_subscriber.no_runtime_event(event(duration: 10))
|
46
|
+
assert_equal 5000.0, RuntimeLogSubscriber.runtime
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'does not log anything when not given block' do
|
50
|
+
class MuteLogSubscriber < SweetNotifications::LogSubscriber
|
51
|
+
event :mute_event, runtime: true
|
52
|
+
end
|
53
|
+
log_subscriber = MuteLogSubscriber.new
|
54
|
+
log_subscriber.mute_event(event(duration: 5))
|
55
|
+
assert_equal [], @logger.logged(:info)
|
56
|
+
assert_equal [], @logger.logged(:debug)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'listens to events when attached to a namespace' do
|
60
|
+
class AttachedLogSubscriber < SweetNotifications::LogSubscriber
|
61
|
+
event :important_stuff, runtime: true do
|
62
|
+
info 'received!'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
AttachedLogSubscriber.attach_to :namespace
|
66
|
+
ActiveSupport::Notifications.instrument 'important_stuff.namespace' do
|
67
|
+
'OK'
|
68
|
+
end
|
69
|
+
assert_equal ['received!'], @logger.logged(:info)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe '.runtime' do
|
74
|
+
it 'can be incremented' do
|
75
|
+
log_subscriber = Class.new(SweetNotifications::LogSubscriber)
|
76
|
+
assert_equal 0, log_subscriber.runtime
|
77
|
+
log_subscriber.runtime += 1.2
|
78
|
+
assert_equal 1.2, log_subscriber.runtime
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'does not share runtime across subscribers' do
|
82
|
+
first = Class.new(SweetNotifications::LogSubscriber)
|
83
|
+
second = Class.new(SweetNotifications::LogSubscriber)
|
84
|
+
|
85
|
+
first.runtime += 100
|
86
|
+
second.runtime += 200
|
87
|
+
refute_equal first.runtime, second.runtime
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe '.reset_runtime' do
|
92
|
+
before :each do
|
93
|
+
@log_subscriber = Class.new(SweetNotifications::LogSubscriber)
|
94
|
+
@log_subscriber.runtime = 2000
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'returns the current runtime' do
|
98
|
+
assert_equal 2000, @log_subscriber.reset_runtime
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'sets the current runtime to 0' do
|
102
|
+
@log_subscriber.reset_runtime
|
103
|
+
assert_equal 0, @log_subscriber.runtime
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe '#message' do
|
108
|
+
class MessageLogSubscriber < SweetNotifications::LogSubscriber
|
109
|
+
color ActiveSupport::LogSubscriber::CYAN,
|
110
|
+
ActiveSupport::LogSubscriber::MAGENTA
|
111
|
+
end
|
112
|
+
|
113
|
+
subject { MessageLogSubscriber.new }
|
114
|
+
|
115
|
+
it 'uses given colors for title' do
|
116
|
+
subject.colorize_logging = true
|
117
|
+
odd = subject.message(event, 'Label', 'body')
|
118
|
+
even = subject.message(event, 'Label', 'body')
|
119
|
+
assert_match ActiveSupport::LogSubscriber::CYAN, odd
|
120
|
+
assert_match ActiveSupport::LogSubscriber::MAGENTA, even
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'uses only one color when alternate color is not defined' do
|
124
|
+
subject = Class.new(SweetNotifications::LogSubscriber) do
|
125
|
+
color ActiveSupport::LogSubscriber::CYAN
|
126
|
+
end.new
|
127
|
+
subject.colorize_logging = true
|
128
|
+
assert_match(ActiveSupport::LogSubscriber::CYAN,
|
129
|
+
subject.message(event, 'Label', 'body'))
|
130
|
+
|
131
|
+
assert_match(ActiveSupport::LogSubscriber::CYAN,
|
132
|
+
subject.message(event, 'Label', 'body'))
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'alternates between bold and normal body text' do
|
136
|
+
subject.colorize_logging = true
|
137
|
+
odd = subject.message(event, 'Label', 'body')
|
138
|
+
even = subject.message(event, 'Label', 'body')
|
139
|
+
assert !odd.include?(ActiveSupport::LogSubscriber::BOLD + 'body')
|
140
|
+
assert even.include?(ActiveSupport::LogSubscriber::BOLD + 'body')
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'does not use colors when setting is disabled' do
|
144
|
+
subject.colorize_logging = false
|
145
|
+
message = subject.message(event, 'Label', 'body')
|
146
|
+
assert !message.include?(ActiveSupport::LogSubscriber::CYAN)
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe SweetNotifications::Railtie do
|
4
|
+
it 'has a railtie name' do
|
5
|
+
railtie = SweetNotifications.railtie('test_railtie', nil, nil)
|
6
|
+
assert_equal 'test_railtie', railtie.railtie_name
|
7
|
+
end
|
8
|
+
|
9
|
+
describe 'initializer' do
|
10
|
+
it 'adds an initializer' do
|
11
|
+
railtie = SweetNotifications.railtie('log_subscriber', nil, nil)
|
12
|
+
assert_equal 1, railtie.initializers.length
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'attaches log subscriber to namespace' do
|
16
|
+
mock = MiniTest::Mock.new
|
17
|
+
mock.expect :attach_to, true, [:log_subscriber]
|
18
|
+
railtie = SweetNotifications.railtie('log_subscriber', mock, Module.new)
|
19
|
+
railtie.run_initializers
|
20
|
+
assert mock.verify
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'injects controller runtime to ActionController::Base' do
|
24
|
+
log_subscriber = Class.new(SweetNotifications::LogSubscriber)
|
25
|
+
runtime = SweetNotifications.controller_runtime('injection',
|
26
|
+
log_subscriber)
|
27
|
+
railtie = SweetNotifications.railtie('test', log_subscriber, runtime)
|
28
|
+
railtie.run_initializers
|
29
|
+
assert_includes ActionController::Base.ancestors, runtime
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe SweetNotifications do
|
4
|
+
include ActiveSupport::LogSubscriber::TestHelper
|
5
|
+
|
6
|
+
describe '.subscribe' do
|
7
|
+
it 'creates a railtie' do
|
8
|
+
railtie, _ = SweetNotifications.subscribe 'railtie_create' do
|
9
|
+
end
|
10
|
+
assert railtie < Rails::Railtie
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'initializes a log subscriber' do
|
14
|
+
_, log_subscriber = SweetNotifications.subscribe 'subscriber_create' do
|
15
|
+
event :foo, runtime: true
|
16
|
+
end
|
17
|
+
assert log_subscriber < ActiveSupport::LogSubscriber
|
18
|
+
assert log_subscriber.new.public_methods(false).include?(:foo)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'binds log subscriber to notifications' do
|
22
|
+
railtie, _ = SweetNotifications.subscribe 'sweet' do
|
23
|
+
event :test do |event|
|
24
|
+
info message(event, 'Test', 'blah blah')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
railtie.run_initializers
|
29
|
+
ActiveSupport::Notifications.instrument 'test.sweet' do
|
30
|
+
'ok'
|
31
|
+
end
|
32
|
+
assert_match(/Test \(\d\.\d{2}ms\) blah blah/, @logger.logged(:info)[0])
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'binds to current Rails app directly when the app is initialized' do
|
36
|
+
module ::Rails
|
37
|
+
def self.application
|
38
|
+
Struct.new(:initialized?).new(true)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
railtie, _ = SweetNotifications.subscribe 'sweet' do
|
43
|
+
event :direct do |event|
|
44
|
+
info message(event, 'Direct', 'foo bar')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
assert_equal nil, railtie
|
49
|
+
module ::Rails
|
50
|
+
class << self
|
51
|
+
undef application
|
52
|
+
end
|
53
|
+
end
|
54
|
+
ActiveSupport::Notifications.instrument 'direct.sweet' do
|
55
|
+
'ok'
|
56
|
+
end
|
57
|
+
assert_match(/Direct \(\d\.\d{2}ms\) foo bar/, @logger.logged(:info)[0])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
ENV['RAILS_ENV'] = 'test'
|
2
|
+
require 'simplecov'
|
3
|
+
|
4
|
+
SimpleCov.start do
|
5
|
+
add_filter 'test'
|
6
|
+
command_name 'Mintest'
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'minitest/autorun'
|
10
|
+
require 'minitest/spec'
|
11
|
+
require 'minitest/pride'
|
12
|
+
require 'sweet_notifications'
|
13
|
+
require 'active_support/test_case'
|
14
|
+
require 'securerandom'
|
15
|
+
|
16
|
+
class ActiveSupport::TestCase
|
17
|
+
class << self
|
18
|
+
remove_method :describe
|
19
|
+
end
|
20
|
+
|
21
|
+
extend MiniTest::Spec::DSL
|
22
|
+
register_spec_type(/ControllerRuntime$/, ActionController::TestCase)
|
23
|
+
register_spec_type(self)
|
24
|
+
end
|
25
|
+
|
26
|
+
module ActionController
|
27
|
+
TestRoutes = ActionDispatch::Routing::RouteSet.new
|
28
|
+
TestRoutes.draw do
|
29
|
+
match ':controller(/:action)', via: [:all]
|
30
|
+
end
|
31
|
+
|
32
|
+
class Base
|
33
|
+
include ActionController::Testing
|
34
|
+
include TestRoutes.url_helpers
|
35
|
+
end
|
36
|
+
|
37
|
+
class ActionController::TestCase
|
38
|
+
setup do
|
39
|
+
@routes = TestRoutes
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
metadata
ADDED
@@ -0,0 +1,227 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sweet_notifications
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ville Lautanala
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-06-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: request_store
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: railties
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '4.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '4.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: actionpack
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '4.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '4.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.6'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.6'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: minitest
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rake
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '10.3'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '10.3'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: yard
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.8.7
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 0.8.7
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: appraisal
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '1.0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '1.0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: simplecov
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: 0.8.2
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: 0.8.2
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: rubocop
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: 0.22.0
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: 0.22.0
|
167
|
+
description: Syntactic sugar for ActiveSupport::LogSubscriber for easy instrumentation
|
168
|
+
and logging from third-party libraries.
|
169
|
+
email:
|
170
|
+
- lautis@gmail.com
|
171
|
+
executables: []
|
172
|
+
extensions: []
|
173
|
+
extra_rdoc_files: []
|
174
|
+
files:
|
175
|
+
- ".gitignore"
|
176
|
+
- ".rubocop.yml"
|
177
|
+
- ".travis.yml"
|
178
|
+
- Appraisals
|
179
|
+
- CONTRIBUTING.md
|
180
|
+
- Gemfile
|
181
|
+
- LICENSE.txt
|
182
|
+
- README.md
|
183
|
+
- Rakefile
|
184
|
+
- gemfiles/rails_4.0.gemfile
|
185
|
+
- gemfiles/rails_4.1.gemfile
|
186
|
+
- lib/sweet_notifications.rb
|
187
|
+
- lib/sweet_notifications/controller_runtime.rb
|
188
|
+
- lib/sweet_notifications/log_subscriber.rb
|
189
|
+
- lib/sweet_notifications/railtie.rb
|
190
|
+
- lib/sweet_notifications/version.rb
|
191
|
+
- sweet_notifications.gemspec
|
192
|
+
- test/controller_runtime_test.rb
|
193
|
+
- test/log_subscriber_test.rb
|
194
|
+
- test/railtie_test.rb
|
195
|
+
- test/sweet_notifications_test.rb
|
196
|
+
- test/test_helper.rb
|
197
|
+
homepage: https://github.com/lautis/sweet_notifications
|
198
|
+
licenses:
|
199
|
+
- MIT
|
200
|
+
metadata: {}
|
201
|
+
post_install_message:
|
202
|
+
rdoc_options: []
|
203
|
+
require_paths:
|
204
|
+
- lib
|
205
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
206
|
+
requirements:
|
207
|
+
- - "~>"
|
208
|
+
- !ruby/object:Gem::Version
|
209
|
+
version: '2.0'
|
210
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
211
|
+
requirements:
|
212
|
+
- - ">="
|
213
|
+
- !ruby/object:Gem::Version
|
214
|
+
version: '0'
|
215
|
+
requirements: []
|
216
|
+
rubyforge_project:
|
217
|
+
rubygems_version: 2.2.2
|
218
|
+
signing_key:
|
219
|
+
specification_version: 4
|
220
|
+
summary: Syntactic sugar for ActiveSupport::LogSubscriber.
|
221
|
+
test_files:
|
222
|
+
- test/controller_runtime_test.rb
|
223
|
+
- test/log_subscriber_test.rb
|
224
|
+
- test/railtie_test.rb
|
225
|
+
- test/sweet_notifications_test.rb
|
226
|
+
- test/test_helper.rb
|
227
|
+
has_rdoc:
|