validation_rage 0.0.1
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.
- data/.gitignore +17 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +80 -0
- data/Rakefile +9 -0
- data/lib/validation_rage/base_notifier.rb +18 -0
- data/lib/validation_rage/controller_extension.rb +28 -0
- data/lib/validation_rage/fnord_metric_notifier.rb +34 -0
- data/lib/validation_rage/log_notifier.rb +14 -0
- data/lib/validation_rage/model_extension.rb +12 -0
- data/lib/validation_rage/rails.rb +43 -0
- data/lib/validation_rage/udp_notifier.rb +17 -0
- data/lib/validation_rage/validation_rage_notifier.rb +19 -0
- data/lib/validation_rage/version.rb +3 -0
- data/lib/validation_rage.rb +13 -0
- data/test/test_helper.rb +21 -0
- data/test/validation_rage/base_notifier_test.rb +21 -0
- data/test/validation_rage/controller_extension_test.rb +60 -0
- data/test/validation_rage/log_notifier_test.rb +23 -0
- data/test/validation_rage/model_extension_test.rb +29 -0
- data/test/validation_rage/udp_notifier_test.rb +21 -0
- data/validation_rage.gemspec +21 -0
- metadata +121 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Michael Bumann
|
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,80 @@
|
|
1
|
+
# ValidationRage
|
2
|
+
|
3
|
+
ValidationRage is a gem to capture validation errors from your Ruby application.
|
4
|
+
The goal is to identify usability issues in your application that are caused by validations.
|
5
|
+
|
6
|
+
Imaging a form with several field validations. ValidationRage makes it super easy to get information on what fields the users experience validation errors (and might leave because of that).
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
gem 'validation_rage'
|
13
|
+
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
By default ValidationRage will hook into ActiveRecord::Base and log all validation errors to your Rails log.
|
18
|
+
|
19
|
+
ValidationRage comes with an rails engine to configure your application. "config" in the following examples refer to Rails.application.config
|
20
|
+
You can configure if you want to hook into your models or controllers.
|
21
|
+
|
22
|
+
### Logging on model level ###
|
23
|
+
|
24
|
+
You can hook ValidationRage into your classes that are ActiveModel::Validation compatible.
|
25
|
+
|
26
|
+
example configuration:
|
27
|
+
|
28
|
+
config.validation_rage.attach_to = [User, Account, Session] # hook into the User, Account, Session classes and attach an after_validation callback to track invalid records
|
29
|
+
|
30
|
+
### Logging on controller level ###
|
31
|
+
|
32
|
+
The problem with attaching ValidationRage to your models is that you do not have any information about the context: where did the error happen? what parameters causes the error?
|
33
|
+
That's why you can hook ValidationRage into your controllers. ValidationRage will add an after_callback checking your instance variables for errors.
|
34
|
+
|
35
|
+
example configuration:
|
36
|
+
|
37
|
+
config.validation_rage.attach_to = ["users#create", "session#create"] # hook into the Users and Session controler create actions
|
38
|
+
|
39
|
+
# using * to match any action or any controller:
|
40
|
+
|
41
|
+
config.validation_rage.attach_to = ["*#create"] # hook into every create action. - this is done by adding the after_filter to the ApplicationController
|
42
|
+
config.validation_rage.attach_to = ["users#*"] # hook into every action in the users controler.
|
43
|
+
|
44
|
+
example configuration with both model and controller level logging:
|
45
|
+
|
46
|
+
config.validation_rage.attach_to = ["users#create", Company] # hook into the create action of the UsersController AND the Company model
|
47
|
+
|
48
|
+
|
49
|
+
### Using different notifiers ###
|
50
|
+
|
51
|
+
ValidationRage uses ActiveSupport::Notifications to publish a notification message when an validation error happened. This makes it super easy to write a listener to those events and process the validation error information.
|
52
|
+
This gem comes with different Notifiers and since the integrate with ActiveSupport::Notifiers you can use several notifiers at the same time and write your own notifer.
|
53
|
+
|
54
|
+
#### LogNotifier ####
|
55
|
+
|
56
|
+
uses the logger to log your validation errors.
|
57
|
+
|
58
|
+
configuration:
|
59
|
+
|
60
|
+
config.validation_rage.notifier["Log"] = {:log_level => :warn, :logger => Logger.new("log/validations.log")}
|
61
|
+
|
62
|
+
#### UdpNotifier ####
|
63
|
+
|
64
|
+
send the errors as JSON to a UDP server server
|
65
|
+
|
66
|
+
configuration:
|
67
|
+
|
68
|
+
config.validation_rage.notifier["Udp"] = {:host => "localhost", :port => 3333}
|
69
|
+
|
70
|
+
|
71
|
+
#### ValidationRageNotifer ####
|
72
|
+
|
73
|
+
send the errors to the ValidationRage Application which gives you a nice accessible interface to analyze your data.
|
74
|
+
Signup at validationrage.com to get your API key
|
75
|
+
|
76
|
+
configuration:
|
77
|
+
|
78
|
+
config.validation_rage.notifier["ValidationRage"] = {:api_key => "<YOUR API KEY>"}
|
79
|
+
|
80
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module ValidationRage
|
2
|
+
class BaseNotifier
|
3
|
+
class NotImplementedError < StandardError; end
|
4
|
+
|
5
|
+
def initialize(args={})
|
6
|
+
end
|
7
|
+
def call(event_name, payload)
|
8
|
+
raise NotImplementedError.new("your notifer must implement a call(event_name, payload) method")
|
9
|
+
end
|
10
|
+
def subscribe!
|
11
|
+
ActiveSupport::Notifications.subscribe(/validation_rage:.*/, self)
|
12
|
+
end
|
13
|
+
|
14
|
+
def data_present?(payload)
|
15
|
+
payload.values.first && !payload.values.first.empty?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module ValidationRage
|
2
|
+
module ControllerExtension
|
3
|
+
|
4
|
+
def notify_validation_rage
|
5
|
+
objects_with_errors = self.instance_variables.collect {|var_name| instance_variable_get(var_name) if validation_rage_errors_present?(var_name) }.compact
|
6
|
+
objects_with_errors.each do |o|
|
7
|
+
ActiveSupport::Notifications.publish("validation_rage:errors", {o.class.name => o.errors.to_hash, :context => self.validation_rage_context })
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def validation_rage_errors_present?(var_name)
|
12
|
+
return false if var_name.to_s =~ /^@_/ # ignore variable names marked with "_" - those are by convention internal only
|
13
|
+
obj = instance_variable_get(var_name)
|
14
|
+
obj.respond_to?(:errors) && !obj.errors.empty?
|
15
|
+
end
|
16
|
+
|
17
|
+
def validation_rage_context
|
18
|
+
{
|
19
|
+
:controller => params[:controller],
|
20
|
+
:action => params[:action],
|
21
|
+
:request_path => request.path,
|
22
|
+
:params => request.filtered_parameters,
|
23
|
+
:request_uuid => request.uuid,
|
24
|
+
:referrer => request.referrer
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "fnordmetric"
|
2
|
+
module ValidationRage
|
3
|
+
class FnordMetricNotifier < BaseNotifier
|
4
|
+
attr_accessor :fnord
|
5
|
+
|
6
|
+
def initialize(args={})
|
7
|
+
self.fnord = FnordMetric::API.new(:redis_url => args[:redis_url])
|
8
|
+
end
|
9
|
+
|
10
|
+
# I guess this is toooooo sloooow but anyhow let's play with it
|
11
|
+
def call(event_name, payload)
|
12
|
+
return unless data_present?(payload)
|
13
|
+
|
14
|
+
# global validation error event
|
15
|
+
self.fnord.event({
|
16
|
+
:_type => event_name,
|
17
|
+
:payload => payload
|
18
|
+
})
|
19
|
+
# class level validation error event
|
20
|
+
self.fnord.event({
|
21
|
+
:_type => "validation_rage_error.#{payload.keys.first.to_s.downcase}",
|
22
|
+
:payload => payload.values.first.keys
|
23
|
+
})
|
24
|
+
# two events are enough for now
|
25
|
+
## attribute level validation error event
|
26
|
+
#payload.values.first.each do |attribute, error_messages|
|
27
|
+
# self.fnord.event({
|
28
|
+
# :_type => "validation_rage_error.#{payload.keys.first.to_s.downcase}.#{attribute}",
|
29
|
+
# :payload => error_messages
|
30
|
+
# })
|
31
|
+
#end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module ValidationRage
|
2
|
+
class LogNotifier < BaseNotifier
|
3
|
+
attr_accessor :logger, :log_level
|
4
|
+
def initialize(args)
|
5
|
+
self.logger = args[:logger]
|
6
|
+
self.log_level = args[:log_level] || :warn
|
7
|
+
end
|
8
|
+
# TODO: optimize log format
|
9
|
+
def call(event_name, payload)
|
10
|
+
return if payload.values.first && payload.values.first.empty?
|
11
|
+
self.logger.send(self.log_level, "#{event_name} #{payload}")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module ValidationRage
|
2
|
+
module ModelExtension
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.after_validation(:notify_validation_rage)
|
6
|
+
end
|
7
|
+
|
8
|
+
def notify_validation_rage(context = {})
|
9
|
+
ActiveSupport::Notifications.publish("validation_rage:errors", {self.class.name => self.errors.to_hash, :context => context})
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module ValidationRage
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
|
4
|
+
config.validation_rage = ActiveSupport::OrderedOptions.new
|
5
|
+
|
6
|
+
config.validation_rage.attach_to = []
|
7
|
+
config.validation_rage.attach_to = [ActiveRecord::Base] if defined?(ActiveRecord::Base) # really?!
|
8
|
+
|
9
|
+
config.validation_rage.notifier = {"Log" => {:log_level => :warn, :logger => nil}} # defaults to log everything to the logger
|
10
|
+
|
11
|
+
initializer "validation_rage.configure_subscribers" do |app|
|
12
|
+
# TODO move this into a testable setup method and refactor! -
|
13
|
+
|
14
|
+
if app.config.validation_rage # if validation rage is enabled
|
15
|
+
app.config.validation_rage.notifier.each do |name, options|
|
16
|
+
options[:logger] ||= Rails.logger
|
17
|
+
ValidationRage.const_get("#{name}Notifier").new(options).subscribe! # initialize the notifier and subscribe to the active suppot notification messages
|
18
|
+
end
|
19
|
+
|
20
|
+
# attach validation rage integration extensions to controllers (with after filter) or models (with after_validation filters)
|
21
|
+
controllers = {}
|
22
|
+
app.config.validation_rage.attach_to.each do |klass_or_action|
|
23
|
+
# if its a string we collect the controller and actions to later add a after_filter
|
24
|
+
if klass_or_action.is_a?(String)
|
25
|
+
controller, action = klass_or_action.split("#")
|
26
|
+
controllers[controller] ||= []
|
27
|
+
controllers[controller] << action
|
28
|
+
else
|
29
|
+
klass.send(:include, ValidationRage::ModelExtension)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
# now addingt the after filter to controllers
|
33
|
+
controllers.each do |controller, actions|
|
34
|
+
controller = "Application" if controller == "*"
|
35
|
+
controller_class = "#{controller}Controller".classify.constantize rescue next # just ignore errors for now
|
36
|
+
controller_class.send(:include, ValidationRage::ControllerExtension)
|
37
|
+
options = {:only => actions} unless actions.any? {|a| a == "*"}
|
38
|
+
controller_class.send(:after_filter, :notify_validation_rage, options)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "socket"
|
2
|
+
module ValidationRage
|
3
|
+
class UdpNotifier < BaseNotifier
|
4
|
+
|
5
|
+
attr_accessor :socket, :host, :port
|
6
|
+
def initialize(args)
|
7
|
+
self.socket = UDPSocket.new
|
8
|
+
self.host = args[:host]
|
9
|
+
self.port = args[:port]
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(event_name, payload)
|
13
|
+
self.socket.send(payload.to_json, 0, self.host, self.port)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "socket"
|
2
|
+
module ValidationRage
|
3
|
+
class ValidationRageNotifier < BaseNotifier
|
4
|
+
|
5
|
+
attr_accessor :socket, :host, :port, :api_key
|
6
|
+
def initialize(args)
|
7
|
+
self.socket = UDPSocket.new
|
8
|
+
self.host = "localhost"
|
9
|
+
self.port = 33333
|
10
|
+
self.api_key = args[:api_key]
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(event_name, payload)
|
14
|
+
data = {:api_key => self.api_key, :payload => payload}
|
15
|
+
self.socket.send(data.to_json, 0, self.host, self.port)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "validation_rage/version"
|
2
|
+
require "active_support/notifications"
|
3
|
+
require 'validation_rage/rails' if defined?(Rails)
|
4
|
+
require "json"
|
5
|
+
module ValidationRage
|
6
|
+
autoload :BaseNotifier, "validation_rage/base_notifier"
|
7
|
+
autoload :LogNotifier, "validation_rage/log_notifier"
|
8
|
+
autoload :UdpNotifier, "validation_rage/udp_notifier"
|
9
|
+
autoload :ValidationRageNotifier, "validation_rage/validation_rage_notifier"
|
10
|
+
autoload :FnordMetricNotifier, "validation_rage/fnord_metric_notifier"
|
11
|
+
autoload :ModelExtension, "validation_rage/model_extension"
|
12
|
+
autoload :ControllerExtension, "validation_rage/controller_extension"
|
13
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
require 'bundler/setup'
|
3
|
+
Bundler.require
|
4
|
+
require 'minitest/autorun'
|
5
|
+
require 'minitest/mock'
|
6
|
+
require "mocha"
|
7
|
+
|
8
|
+
require 'validation_rage'
|
9
|
+
|
10
|
+
|
11
|
+
class MockModel
|
12
|
+
def self.after_validation(method)
|
13
|
+
@@after_validation_method = method
|
14
|
+
end
|
15
|
+
def self.after_validation_method
|
16
|
+
@@after_validation_method
|
17
|
+
end
|
18
|
+
def self.name
|
19
|
+
"MockClass"
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class ValidationRage::BaseNotifierTest < MiniTest::Unit::TestCase
|
4
|
+
|
5
|
+
def test_call_raises_a_not_implemented_error
|
6
|
+
assert_raises(ValidationRage::BaseNotifier::NotImplementedError) { ValidationRage::BaseNotifier.new.call("event", {}) }
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_subscribe_to_validation_rage_events
|
10
|
+
notifier = ValidationRage::BaseNotifier.new
|
11
|
+
ActiveSupport::Notifications.expects(:subscribe).with(/validation_rage:.*/, notifier)
|
12
|
+
notifier.subscribe!
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_data_present
|
16
|
+
notifier = ValidationRage::BaseNotifier.new
|
17
|
+
assert notifier.data_present?("klass" => {:error => :message})
|
18
|
+
assert !notifier.data_present?("klass" => {})
|
19
|
+
assert !notifier.data_present?({})
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
# TODO: guess this test could be written nicer
|
4
|
+
class MockController
|
5
|
+
def request
|
6
|
+
OpenStruct.new(:filtered_parameters => ["filtered", "params"], :path => "/mock/path", :uuid => "uuid", :referrer => "referrer")
|
7
|
+
end
|
8
|
+
def params
|
9
|
+
{:controller => "Mock", :action => "create"}
|
10
|
+
end
|
11
|
+
def initialize(records={})
|
12
|
+
records.each do |name,record|
|
13
|
+
instance_variable_set("@#{name}", record)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
class ValidationRage::ControllerExtensionTest < MiniTest::Unit::TestCase
|
18
|
+
|
19
|
+
def setup
|
20
|
+
@klass = Class.new(MockController)
|
21
|
+
@klass.send(:include, ValidationRage::ControllerExtension)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_errors_present
|
25
|
+
assert !@klass.new(:var => "not responding to errors").validation_rage_errors_present?(:"@var")
|
26
|
+
assert !@klass.new(:var => mock(:errors => [])).validation_rage_errors_present?(:"@var")
|
27
|
+
assert !@klass.new(:_var => "internal only vars should be ignored").validation_rage_errors_present?(:"@_var")
|
28
|
+
assert @klass.new(:var => mock(:errors => ["not empty"])).validation_rage_errors_present?(:"@var")
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_validation_rage_context
|
32
|
+
assert_equal({
|
33
|
+
:controller => "Mock",
|
34
|
+
:action => "create",
|
35
|
+
:request_path => "/mock/path",
|
36
|
+
:params => ["filtered","params"],
|
37
|
+
:request_uuid => "uuid",
|
38
|
+
:referrer => "referrer"
|
39
|
+
}, @klass.new.validation_rage_context)
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_notify_validation_rage
|
43
|
+
record = MockModel.new
|
44
|
+
record.expects(:errors).at_least_once.returns(mock(:"empty?"=>false, :to_hash=>{:errors => :hash}))
|
45
|
+
controller_instance = @klass.new(:record => record, :foo => :bar)
|
46
|
+
ActiveSupport::Notifications.expects(:publish).with("validation_rage:errors", {
|
47
|
+
"MockClass" => {:errors => :hash},
|
48
|
+
:context => {
|
49
|
+
:controller => "Mock",
|
50
|
+
:action => "create",
|
51
|
+
:request_path => "/mock/path",
|
52
|
+
:params => ["filtered","params"],
|
53
|
+
:request_uuid => "uuid",
|
54
|
+
:referrer => "referrer"
|
55
|
+
}
|
56
|
+
})
|
57
|
+
controller_instance.notify_validation_rage
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class ValidationRage::LogNotifierTest < MiniTest::Unit::TestCase
|
4
|
+
|
5
|
+
|
6
|
+
def test_defaul_log_level
|
7
|
+
assert_equal :warn, ValidationRage::LogNotifier.new({}).log_level
|
8
|
+
end
|
9
|
+
def test_log_validation_errors_to_logger
|
10
|
+
payload = {"Class" => {:name => ["missing"]}}
|
11
|
+
mocked_logger = mock()
|
12
|
+
mocked_logger.expects(:info).with("event_name #{payload.inspect}")
|
13
|
+
log_notifier = ValidationRage::LogNotifier.new(:logger => mocked_logger, :log_level => :info)
|
14
|
+
log_notifier.call("event_name", payload)
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_ignore_empty_errors
|
18
|
+
mocked_logger = mock()
|
19
|
+
mocked_logger.expects(:warn).never
|
20
|
+
notifier = ValidationRage::LogNotifier.new(:logger => mocked_logger)
|
21
|
+
notifier.call("event_name", "Class" => {})
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
# TODO: guess this test could be written nicer
|
4
|
+
class ValidationRage::ModelExtensionTest < MiniTest::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@klass = Class.new(MockModel)
|
8
|
+
@klass.send(:include, ValidationRage::ModelExtension)
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_register_after_validation_callback
|
12
|
+
assert_equal :notify_validation_rage, @klass.after_validation_method
|
13
|
+
assert @klass.new.respond_to?(:notify_validation_rage)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_publish_active_support_notification
|
17
|
+
instance = @klass.new
|
18
|
+
instance.expects(:errors).returns(mock(:to_hash=>{:errors => :hash}))
|
19
|
+
ActiveSupport::Notifications.expects(:publish).with("validation_rage:errors", {"MockClass" => {:errors => :hash}, :context => {}})
|
20
|
+
instance.notify_validation_rage
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_passing_a_context_hash_to_notification_call
|
24
|
+
instance = @klass.new
|
25
|
+
instance.expects(:errors).returns(mock(:to_hash=>{:errors => :hash}))
|
26
|
+
ActiveSupport::Notifications.expects(:publish).with("validation_rage:errors", {"MockClass" => {:errors => :hash}, :context => {:controller => "Users", :action => "edit"}})
|
27
|
+
instance.notify_validation_rage({:controller => "Users", :action => "edit"})
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "socket"
|
3
|
+
class ValidationRage::UdpNotifierTest < MiniTest::Unit::TestCase
|
4
|
+
|
5
|
+
def test_connect_to_socket
|
6
|
+
UDPSocket.expects(:new).returns("socket")
|
7
|
+
notifier = ValidationRage::UdpNotifier.new(:host => "localhost", :port => 33333)
|
8
|
+
assert_equal "socket", notifier.socket
|
9
|
+
assert_equal "localhost", notifier.host
|
10
|
+
assert_equal 33333, notifier.port
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_send_json_encoded_payload_through_socket
|
14
|
+
notifier = ValidationRage::UdpNotifier.new(:host => "host", :port => "port")
|
15
|
+
payload = {"Class" => {:error => :message}}
|
16
|
+
socket = mock()
|
17
|
+
socket.expects(:send).with(payload.to_json,0, "host", "port")
|
18
|
+
notifier.expects(:socket).returns(socket)
|
19
|
+
notifier.call("event_name", payload)
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/validation_rage/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Michael Bumann"]
|
6
|
+
gem.email = ["michael@railslove.com"]
|
7
|
+
gem.description = %q{log active model validation errors to get better insights in the usability of your forms}
|
8
|
+
gem.summary = %q{log active model validation errors to get better insights in the usability of your forms}
|
9
|
+
gem.homepage = ""
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "validation_rage"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = ValidationRage::VERSION
|
17
|
+
gem.add_development_dependency 'rake'
|
18
|
+
gem.add_development_dependency 'mocha'
|
19
|
+
gem.add_dependency 'activesupport'
|
20
|
+
gem.add_dependency 'json'
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: validation_rage
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Michael Bumann
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-07-10 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: &2156416240 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2156416240
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: mocha
|
27
|
+
requirement: &2156459260 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2156459260
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: activesupport
|
38
|
+
requirement: &2156470080 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2156470080
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: json
|
49
|
+
requirement: &2156465740 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2156465740
|
58
|
+
description: log active model validation errors to get better insights in the usability
|
59
|
+
of your forms
|
60
|
+
email:
|
61
|
+
- michael@railslove.com
|
62
|
+
executables: []
|
63
|
+
extensions: []
|
64
|
+
extra_rdoc_files: []
|
65
|
+
files:
|
66
|
+
- .gitignore
|
67
|
+
- .travis.yml
|
68
|
+
- Gemfile
|
69
|
+
- LICENSE
|
70
|
+
- README.md
|
71
|
+
- Rakefile
|
72
|
+
- lib/validation_rage.rb
|
73
|
+
- lib/validation_rage/base_notifier.rb
|
74
|
+
- lib/validation_rage/controller_extension.rb
|
75
|
+
- lib/validation_rage/fnord_metric_notifier.rb
|
76
|
+
- lib/validation_rage/log_notifier.rb
|
77
|
+
- lib/validation_rage/model_extension.rb
|
78
|
+
- lib/validation_rage/rails.rb
|
79
|
+
- lib/validation_rage/udp_notifier.rb
|
80
|
+
- lib/validation_rage/validation_rage_notifier.rb
|
81
|
+
- lib/validation_rage/version.rb
|
82
|
+
- test/test_helper.rb
|
83
|
+
- test/validation_rage/base_notifier_test.rb
|
84
|
+
- test/validation_rage/controller_extension_test.rb
|
85
|
+
- test/validation_rage/log_notifier_test.rb
|
86
|
+
- test/validation_rage/model_extension_test.rb
|
87
|
+
- test/validation_rage/udp_notifier_test.rb
|
88
|
+
- validation_rage.gemspec
|
89
|
+
homepage: ''
|
90
|
+
licenses: []
|
91
|
+
post_install_message:
|
92
|
+
rdoc_options: []
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ! '>='
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
none: false
|
103
|
+
requirements:
|
104
|
+
- - ! '>='
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 1.8.10
|
110
|
+
signing_key:
|
111
|
+
specification_version: 3
|
112
|
+
summary: log active model validation errors to get better insights in the usability
|
113
|
+
of your forms
|
114
|
+
test_files:
|
115
|
+
- test/test_helper.rb
|
116
|
+
- test/validation_rage/base_notifier_test.rb
|
117
|
+
- test/validation_rage/controller_extension_test.rb
|
118
|
+
- test/validation_rage/log_notifier_test.rb
|
119
|
+
- test/validation_rage/model_extension_test.rb
|
120
|
+
- test/validation_rage/udp_notifier_test.rb
|
121
|
+
has_rdoc:
|