activecleaner 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +21 -0
- data/README.md +96 -0
- data/lib/active_cleaner/base_cleaner.rb +48 -0
- data/lib/active_cleaner/helper_methods.rb +24 -0
- data/lib/active_cleaner/markdown_cleaner.rb +32 -0
- data/lib/active_cleaner/string_cleaner.rb +18 -0
- data/lib/active_cleaner/text_cleaner.rb +30 -0
- data/lib/active_cleaner/version.rb +8 -0
- data/lib/active_cleaner.rb +64 -0
- data/lib/activecleaner.rb +3 -0
- data/spec/cases/inherit_spec.rb +122 -0
- data/spec/cases/nilify_spec.rb +101 -0
- data/spec/cases/simple_spec.rb +101 -0
- data/spec/lib/active_cleaner/markdown_cleaner_spec.rb +67 -0
- data/spec/lib/active_cleaner/string_cleaner_spec.rb +45 -0
- data/spec/lib/active_cleaner/text_cleaner_spec.rb +56 -0
- data/spec/lib/active_cleaner_spec.rb +4 -0
- data/spec/spec_helper.rb +9 -0
- metadata +122 -0
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) Maxime Garcia
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
data/README.md
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
# ActiveCleaner
|
2
|
+
|
3
|
+
`ActiveCleaner` is a set of helpers that helps you in cleaning user-typed content in your ActiveModel depending models (ActiveRecord, Mongoid...)
|
4
|
+
|
5
|
+
Extra spaces mean extra storage. And it could ruin your indexes and your sortings.
|
6
|
+
|
7
|
+
Tired of doing everywhere:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
before_validation :clean_title
|
11
|
+
|
12
|
+
def clean_title
|
13
|
+
unless title.nil?
|
14
|
+
self.title = title.squish
|
15
|
+
end
|
16
|
+
self.title = nil if title.blank?
|
17
|
+
|
18
|
+
true
|
19
|
+
end
|
20
|
+
```
|
21
|
+
|
22
|
+
### Cleaners included
|
23
|
+
|
24
|
+
* `:string` (StringCleaner, the default one) : cleans all the space characters. It turns `" A \n \t title \t "` into `"A title"`.
|
25
|
+
* `:text` (TextCleaner) : like `:string`, but preserves new lines (with a max of 2 successive new lines). Usefull when the field is rendered with the `simple_format` Rails helper.
|
26
|
+
* `:markdown` (MarkdownCleaner) : like `:text`, but preserves spaces in the begining of lines (the indentation). Usefull for... markdown!
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
## Installation
|
31
|
+
|
32
|
+
Add the gem to your Gemfile:
|
33
|
+
|
34
|
+
gem 'activecleaner'
|
35
|
+
|
36
|
+
Or install with RubyGems:
|
37
|
+
|
38
|
+
$ gem install activecleaner
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
## Usage
|
43
|
+
|
44
|
+
### Basic usage
|
45
|
+
|
46
|
+
Add `include ActiveCleaner` in your model and also do:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
clean :field_1, :field_2 ... :field_n, options_1: :value, options_2: :value
|
50
|
+
```
|
51
|
+
|
52
|
+
### Options
|
53
|
+
|
54
|
+
* `:as` (default is `:string`) : the symbol name of the cleaner.
|
55
|
+
* `:nilify` (default is `false`) : set to `nil` when the field was or is cleaned to `""`.
|
56
|
+
|
57
|
+
### Example
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
class Post
|
61
|
+
include Mongoid::Document
|
62
|
+
include ActiveCleaner
|
63
|
+
|
64
|
+
field :title
|
65
|
+
field :subtitle
|
66
|
+
clean :title, :subtitle, nilify: true
|
67
|
+
|
68
|
+
field :body
|
69
|
+
clean :body, as: :text, nilify: true
|
70
|
+
end
|
71
|
+
```
|
72
|
+
|
73
|
+
## Contributing
|
74
|
+
|
75
|
+
Contributions and bug reports are welcome.
|
76
|
+
|
77
|
+
Clone the repository and run `bundle install` to setup the development environment.
|
78
|
+
|
79
|
+
Provide a case spec according to your changes/needs, taking example on existing ones (in `spec/cases`).
|
80
|
+
|
81
|
+
To run the specs:
|
82
|
+
|
83
|
+
bundle exec rspec
|
84
|
+
|
85
|
+
You can also use `guard` to run the specs during dev.
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
## Credits
|
90
|
+
|
91
|
+
* Maxime Garcia [emaxime.com](http://emaxime.com) [@maximegarcia](http://twitter.com/maximegarcia)
|
92
|
+
|
93
|
+
|
94
|
+
[License](https://github.com/maximeg/activecleaner/blob/master/LCENSE)
|
95
|
+
\- [Report a bug](https://github.com/maximeg/activecleaner/issues)
|
96
|
+
[![Continuous Integration status](https://secure.travis-ci.org/maximeg/activecleaner.png)](http://travis-ci.org/maximeg/activecleaner)
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module ActiveCleaner
|
4
|
+
class BaseCleaner
|
5
|
+
|
6
|
+
attr_reader :attr_name, :options
|
7
|
+
|
8
|
+
# Accepts options that will be made available through the +options+ reader.
|
9
|
+
def initialize(attr_name, options = {})
|
10
|
+
@attr_name = attr_name
|
11
|
+
@options = {
|
12
|
+
:nilify => false,
|
13
|
+
}.merge(options).freeze
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.kind
|
17
|
+
@kind ||= name.split('::').last.underscore.sub(/_cleaner$/, '').to_sym
|
18
|
+
end
|
19
|
+
|
20
|
+
def kind
|
21
|
+
self.class.kind
|
22
|
+
end
|
23
|
+
|
24
|
+
def clean(record)
|
25
|
+
value = record.read_attribute_for_cleaning(attr_name)
|
26
|
+
|
27
|
+
new_value = clean_value(value, record)
|
28
|
+
|
29
|
+
new_value = nil if @options[:nilify] && nilify_value?(new_value, record)
|
30
|
+
|
31
|
+
record.write_attribute_after_cleaning(attr_name, new_value) unless new_value == value
|
32
|
+
end
|
33
|
+
|
34
|
+
def clean_value(value, record=nil)
|
35
|
+
raise NotImplementedError, "Subclasses must implement a clean(value, record=nil) method."
|
36
|
+
end
|
37
|
+
|
38
|
+
# feel free to subclass for your custom cleaner
|
39
|
+
def nilify_value?(value, record=nil)
|
40
|
+
value == ""
|
41
|
+
end
|
42
|
+
|
43
|
+
def ==(other)
|
44
|
+
kind == other.kind && attr_name == other.attr_name && options == other.options
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module ActiveCleaner
|
4
|
+
module HelperMethods
|
5
|
+
|
6
|
+
def clean(*attr_names)
|
7
|
+
options = attr_names.extract_options!.symbolize_keys
|
8
|
+
attr_names.flatten!
|
9
|
+
|
10
|
+
options[:as] ||= :string
|
11
|
+
|
12
|
+
cleaner = "active_cleaner/#{options.delete(:as)}_cleaner".camelize.constantize
|
13
|
+
|
14
|
+
attr_names.each do |attr_name|
|
15
|
+
clean_with cleaner.new(attr_name, options)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def clean_with(cleaner)
|
20
|
+
self._cleaners[cleaner.attr_name] << cleaner
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module ActiveCleaner
|
4
|
+
class MarkdownCleaner < BaseCleaner
|
5
|
+
|
6
|
+
def clean_value(old_value, record=nil)
|
7
|
+
unless old_value.nil?
|
8
|
+
value = old_value.dup
|
9
|
+
|
10
|
+
value.strip!
|
11
|
+
|
12
|
+
# clean the new lines mess among OS
|
13
|
+
value.gsub!(/\r\n|\r/, "\n")
|
14
|
+
|
15
|
+
# protect stuff to keep with a markup
|
16
|
+
value.gsub!(/\n/, "__NEW_LINE__")
|
17
|
+
value.gsub!(/(?<=__NEW_LINE__)\s+/) {|match| match.gsub(/\s/, "__SPACE__")}
|
18
|
+
|
19
|
+
value.gsub!(/\s+/, " ")
|
20
|
+
value.gsub!(/(__SPACE__|\s)*__NEW_LINE__\s*/, "__NEW_LINE__")
|
21
|
+
value.gsub!(/(__NEW_LINE__){3,}/, "__NEW_LINE____NEW_LINE__")
|
22
|
+
|
23
|
+
# reverse the safe markup
|
24
|
+
value.gsub!(/__NEW_LINE__/, "\n")
|
25
|
+
value.gsub!(/__SPACE__/, " ")
|
26
|
+
|
27
|
+
value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module ActiveCleaner
|
4
|
+
class StringCleaner < BaseCleaner
|
5
|
+
|
6
|
+
def clean_value(old_value, record=nil)
|
7
|
+
unless old_value.nil?
|
8
|
+
value = old_value.dup
|
9
|
+
|
10
|
+
value.strip!
|
11
|
+
value.gsub!(/\s+/, " ")
|
12
|
+
|
13
|
+
value
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module ActiveCleaner
|
4
|
+
class TextCleaner < BaseCleaner
|
5
|
+
|
6
|
+
def clean_value(old_value, record=nil)
|
7
|
+
unless old_value.nil?
|
8
|
+
value = old_value.dup
|
9
|
+
|
10
|
+
value.strip!
|
11
|
+
|
12
|
+
# clean the new lines mess among OS
|
13
|
+
value.gsub!(/\r\n|\r/, "\n")
|
14
|
+
|
15
|
+
# protect stuff to keep with a markup
|
16
|
+
value.gsub!(/\n/, "__NEW_LINE__")
|
17
|
+
|
18
|
+
value.gsub!(/\s+/, " ")
|
19
|
+
value.gsub!(/ ?__NEW_LINE__ ?/, "__NEW_LINE__")
|
20
|
+
value.gsub!(/(__NEW_LINE__){3,}/, "__NEW_LINE____NEW_LINE__")
|
21
|
+
|
22
|
+
# reverse the safe markup
|
23
|
+
value.gsub!(/__NEW_LINE__/, "\n")
|
24
|
+
|
25
|
+
value
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'active_support'
|
4
|
+
#require 'active_support/rails'
|
5
|
+
require 'active_model'
|
6
|
+
|
7
|
+
require 'active_cleaner/helper_methods'
|
8
|
+
|
9
|
+
require 'active_cleaner/base_cleaner'
|
10
|
+
require 'active_cleaner/string_cleaner'
|
11
|
+
require 'active_cleaner/text_cleaner'
|
12
|
+
require 'active_cleaner/markdown_cleaner'
|
13
|
+
|
14
|
+
require 'active_cleaner/version'
|
15
|
+
|
16
|
+
module ActiveCleaner
|
17
|
+
extend ActiveSupport::Concern
|
18
|
+
|
19
|
+
included do
|
20
|
+
|
21
|
+
include ActiveModel::Validations
|
22
|
+
|
23
|
+
extend HelperMethods
|
24
|
+
include HelperMethods
|
25
|
+
|
26
|
+
define_callbacks :cleaning, :scope => :name
|
27
|
+
|
28
|
+
class_attribute :_cleaners
|
29
|
+
self._cleaners = Hash.new { |h,k| h[k] = [] }
|
30
|
+
|
31
|
+
set_callback :validate, :before, :run_cleaners!
|
32
|
+
|
33
|
+
end # included
|
34
|
+
|
35
|
+
|
36
|
+
module ClassMethods
|
37
|
+
|
38
|
+
def inherited(base) #:nodoc:
|
39
|
+
dup = _cleaners.dup
|
40
|
+
base._cleaners = dup.each { |k, v| dup[k] = v.dup }
|
41
|
+
super
|
42
|
+
end
|
43
|
+
|
44
|
+
end # ClassMethods
|
45
|
+
|
46
|
+
|
47
|
+
def run_cleaners!
|
48
|
+
self._cleaners.each do |attr_name, cleaners|
|
49
|
+
cleaners.each do |cleaner|
|
50
|
+
cleaner.clean(self)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
true
|
55
|
+
end
|
56
|
+
|
57
|
+
def read_attribute_for_cleaning(attr_name)
|
58
|
+
send(attr_name)
|
59
|
+
end
|
60
|
+
def write_attribute_after_cleaning(attr_name, value)
|
61
|
+
send(:"#{attr_name}=", value)
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
#
|
5
|
+
# The case
|
6
|
+
#
|
7
|
+
# This is to demonstrate when we want to clean some simple fields
|
8
|
+
# in a common STI scenario.
|
9
|
+
#
|
10
|
+
class Ad
|
11
|
+
include ActiveCleaner
|
12
|
+
|
13
|
+
attr_accessor :title, :name
|
14
|
+
|
15
|
+
clean :title
|
16
|
+
clean :name, as: :string
|
17
|
+
end
|
18
|
+
|
19
|
+
class CarAd < Ad
|
20
|
+
attr_accessor :body
|
21
|
+
|
22
|
+
clean :body, as: :text
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# The specs
|
27
|
+
#
|
28
|
+
describe "Case: an ad and his inherited car ad" do
|
29
|
+
|
30
|
+
describe Ad, "._cleaners" do
|
31
|
+
|
32
|
+
subject { Ad._cleaners }
|
33
|
+
|
34
|
+
it { should have(2).fields_to_clean }
|
35
|
+
|
36
|
+
it "includes a StringCleaner for #title" do
|
37
|
+
subject[:title].first.should eq(ActiveCleaner::StringCleaner.new(:title))
|
38
|
+
end
|
39
|
+
|
40
|
+
it "includes a StringCleaner for #name" do
|
41
|
+
subject[:name].first.should eq(ActiveCleaner::StringCleaner.new(:name))
|
42
|
+
end
|
43
|
+
|
44
|
+
end # describe
|
45
|
+
|
46
|
+
describe CarAd, "._cleaners" do
|
47
|
+
|
48
|
+
subject { CarAd._cleaners }
|
49
|
+
|
50
|
+
it { should have(3).fields_to_clean }
|
51
|
+
|
52
|
+
it "includes a StringCleaner for #title" do
|
53
|
+
subject[:title].first.should eq(ActiveCleaner::StringCleaner.new(:title))
|
54
|
+
end
|
55
|
+
|
56
|
+
it "includes a StringCleaner for #name" do
|
57
|
+
subject[:name].first.should eq(ActiveCleaner::StringCleaner.new(:name))
|
58
|
+
end
|
59
|
+
|
60
|
+
it "includes a TextCleaner for #body" do
|
61
|
+
subject[:body].first.should eq(ActiveCleaner::TextCleaner.new(:body))
|
62
|
+
end
|
63
|
+
|
64
|
+
end # describe
|
65
|
+
|
66
|
+
context "considering a car ad" do
|
67
|
+
|
68
|
+
before do
|
69
|
+
@car_ad = CarAd.new
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "#title, marked as to clean with no type" do
|
73
|
+
|
74
|
+
it "is untouched when legit" do
|
75
|
+
@car_ad.title = "A good title!"
|
76
|
+
@car_ad.valid?
|
77
|
+
@car_ad.title.should eq "A good title!"
|
78
|
+
end
|
79
|
+
|
80
|
+
it "is cleaned as a string" do
|
81
|
+
@car_ad.title = " A \n good \t title! "
|
82
|
+
@car_ad.valid?
|
83
|
+
@car_ad.title.should eq "A good title!"
|
84
|
+
end
|
85
|
+
|
86
|
+
end # describe
|
87
|
+
|
88
|
+
describe "#name, marked as to clean as a string" do
|
89
|
+
|
90
|
+
it "is untouched when legit" do
|
91
|
+
@car_ad.name = "John Doe"
|
92
|
+
@car_ad.valid?
|
93
|
+
@car_ad.name.should eq "John Doe"
|
94
|
+
end
|
95
|
+
|
96
|
+
it "is cleaned as a string" do
|
97
|
+
@car_ad.name = " \t John \n Doe "
|
98
|
+
@car_ad.valid?
|
99
|
+
@car_ad.name.should eq "John Doe"
|
100
|
+
end
|
101
|
+
|
102
|
+
end # describe
|
103
|
+
|
104
|
+
describe "#body, marked as to clean as a text" do
|
105
|
+
|
106
|
+
it "is untouched when legit" do
|
107
|
+
@car_ad.body = "Lorem ipsum\ndolor sit amet.\n\nLorem."
|
108
|
+
@car_ad.valid?
|
109
|
+
@car_ad.body.should eq "Lorem ipsum\ndolor sit amet.\n\nLorem."
|
110
|
+
end
|
111
|
+
|
112
|
+
it "is cleaned as a text" do
|
113
|
+
@car_ad.body = "Lorem \t ipsum \t \n dolor \t sit \t amet.\n\n\nLorem."
|
114
|
+
@car_ad.valid?
|
115
|
+
@car_ad.body.should eq "Lorem ipsum\ndolor sit amet.\n\nLorem."
|
116
|
+
end
|
117
|
+
|
118
|
+
end # describe
|
119
|
+
|
120
|
+
end # context
|
121
|
+
|
122
|
+
end # describe
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
#
|
5
|
+
# The case
|
6
|
+
#
|
7
|
+
# This is to demonstrate when we want to clean some simple fields and nulify them
|
8
|
+
#
|
9
|
+
class OptimizedPost
|
10
|
+
include ActiveCleaner
|
11
|
+
|
12
|
+
attr_accessor :title, :name, :body
|
13
|
+
|
14
|
+
clean :title, nilify: true
|
15
|
+
clean :name, as: :string, nilify: true
|
16
|
+
clean :body, as: :text, nilify: true
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
#
|
21
|
+
# The specs
|
22
|
+
#
|
23
|
+
describe "Case: a simple post with nulify" do
|
24
|
+
|
25
|
+
describe OptimizedPost, "._cleaners" do
|
26
|
+
|
27
|
+
subject { OptimizedPost._cleaners }
|
28
|
+
|
29
|
+
it { should have(3).fields_to_clean }
|
30
|
+
|
31
|
+
it "includes a StringCleaner for #title" do
|
32
|
+
subject[:title].first.should eq(ActiveCleaner::StringCleaner.new(:title, nilify: true))
|
33
|
+
end
|
34
|
+
|
35
|
+
it "includes a StringCleaner for #name" do
|
36
|
+
subject[:name].first.should eq(ActiveCleaner::StringCleaner.new(:name, nilify: true))
|
37
|
+
end
|
38
|
+
|
39
|
+
it "includes a TextCleaner for #body" do
|
40
|
+
subject[:body].first.should eq(ActiveCleaner::TextCleaner.new(:body, nilify: true))
|
41
|
+
end
|
42
|
+
|
43
|
+
end # describe
|
44
|
+
|
45
|
+
context "considering a post" do
|
46
|
+
|
47
|
+
before do
|
48
|
+
@post = OptimizedPost.new
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#title, marked as to clean with no type" do
|
52
|
+
|
53
|
+
it "is untouched when legit" do
|
54
|
+
@post.title = "A good title!"
|
55
|
+
@post.valid?
|
56
|
+
@post.title.should eq "A good title!"
|
57
|
+
end
|
58
|
+
|
59
|
+
it "is nulified" do
|
60
|
+
@post.title = " \n \t "
|
61
|
+
@post.valid?
|
62
|
+
@post.title.should be_nil
|
63
|
+
end
|
64
|
+
|
65
|
+
end # describe
|
66
|
+
|
67
|
+
describe "#name, marked as to clean as a string" do
|
68
|
+
|
69
|
+
it "is untouched when legit" do
|
70
|
+
@post.name = "John Doe"
|
71
|
+
@post.valid?
|
72
|
+
@post.name.should eq "John Doe"
|
73
|
+
end
|
74
|
+
|
75
|
+
it "is nulified" do
|
76
|
+
@post.title = " \n \t "
|
77
|
+
@post.valid?
|
78
|
+
@post.title.should be_nil
|
79
|
+
end
|
80
|
+
|
81
|
+
end # describe
|
82
|
+
|
83
|
+
describe "#body, marked as to clean as a text" do
|
84
|
+
|
85
|
+
it "is untouched when legit" do
|
86
|
+
@post.body = "Lorem ipsum\ndolor sit amet.\n\nLorem."
|
87
|
+
@post.valid?
|
88
|
+
@post.body.should eq "Lorem ipsum\ndolor sit amet.\n\nLorem."
|
89
|
+
end
|
90
|
+
|
91
|
+
it "is nulified" do
|
92
|
+
@post.title = " \n \t "
|
93
|
+
@post.valid?
|
94
|
+
@post.title.should be_nil
|
95
|
+
end
|
96
|
+
|
97
|
+
end # describe
|
98
|
+
|
99
|
+
end # context
|
100
|
+
|
101
|
+
end # describe
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
#
|
5
|
+
# The case
|
6
|
+
#
|
7
|
+
# This is to demonstrate when we want to clean some simple fields
|
8
|
+
#
|
9
|
+
class Post
|
10
|
+
include ActiveCleaner
|
11
|
+
|
12
|
+
attr_accessor :title, :name, :body
|
13
|
+
|
14
|
+
clean :title
|
15
|
+
clean :name, as: :string
|
16
|
+
clean :body, as: :text
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
#
|
21
|
+
# The specs
|
22
|
+
#
|
23
|
+
describe "Case: a simple post" do
|
24
|
+
|
25
|
+
describe Post, "._cleaners" do
|
26
|
+
|
27
|
+
subject { Post._cleaners }
|
28
|
+
|
29
|
+
it { should have(3).fields_to_clean }
|
30
|
+
|
31
|
+
it "includes a StringCleaner for #title" do
|
32
|
+
subject[:title].first.should eq(ActiveCleaner::StringCleaner.new(:title))
|
33
|
+
end
|
34
|
+
|
35
|
+
it "includes a StringCleaner for #name" do
|
36
|
+
subject[:name].first.should eq(ActiveCleaner::StringCleaner.new(:name))
|
37
|
+
end
|
38
|
+
|
39
|
+
it "includes a TextCleaner for #body" do
|
40
|
+
subject[:body].first.should eq(ActiveCleaner::TextCleaner.new(:body))
|
41
|
+
end
|
42
|
+
|
43
|
+
end # describe
|
44
|
+
|
45
|
+
context "considering a post" do
|
46
|
+
|
47
|
+
before do
|
48
|
+
@post = Post.new
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#title, marked as to clean with no type" do
|
52
|
+
|
53
|
+
it "is untouched when legit" do
|
54
|
+
@post.title = "A good title!"
|
55
|
+
@post.valid?
|
56
|
+
@post.title.should eq "A good title!"
|
57
|
+
end
|
58
|
+
|
59
|
+
it "is cleaned as a string" do
|
60
|
+
@post.title = " A \n good \t title! "
|
61
|
+
@post.valid?
|
62
|
+
@post.title.should eq "A good title!"
|
63
|
+
end
|
64
|
+
|
65
|
+
end # describe
|
66
|
+
|
67
|
+
describe "#name, marked as to clean as a string" do
|
68
|
+
|
69
|
+
it "is untouched when legit" do
|
70
|
+
@post.name = "John Doe"
|
71
|
+
@post.valid?
|
72
|
+
@post.name.should eq "John Doe"
|
73
|
+
end
|
74
|
+
|
75
|
+
it "is cleaned as a string" do
|
76
|
+
@post.name = " \t John \n Doe "
|
77
|
+
@post.valid?
|
78
|
+
@post.name.should eq "John Doe"
|
79
|
+
end
|
80
|
+
|
81
|
+
end # describe
|
82
|
+
|
83
|
+
describe "#body, marked as to clean as a text" do
|
84
|
+
|
85
|
+
it "is untouched when legit" do
|
86
|
+
@post.body = "Lorem ipsum\ndolor sit amet.\n\nLorem."
|
87
|
+
@post.valid?
|
88
|
+
@post.body.should eq "Lorem ipsum\ndolor sit amet.\n\nLorem."
|
89
|
+
end
|
90
|
+
|
91
|
+
it "is cleaned as a text" do
|
92
|
+
@post.body = "Lorem \t ipsum \t \n dolor \t sit \t amet.\n\n\nLorem."
|
93
|
+
@post.valid?
|
94
|
+
@post.body.should eq "Lorem ipsum\ndolor sit amet.\n\nLorem."
|
95
|
+
end
|
96
|
+
|
97
|
+
end # describe
|
98
|
+
|
99
|
+
end # context
|
100
|
+
|
101
|
+
end # describe
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe ActiveCleaner::MarkdownCleaner do
|
5
|
+
|
6
|
+
before do
|
7
|
+
@cleaner = ActiveCleaner::MarkdownCleaner.new(:body)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#clean_value" do
|
11
|
+
|
12
|
+
it "doesn't touch legit value" do
|
13
|
+
body = ""
|
14
|
+
body << "= Title =\n"
|
15
|
+
body << "\n"
|
16
|
+
body << "A first paragraph.\n"
|
17
|
+
body << "\n"
|
18
|
+
body << "A **second** one, with a\n"
|
19
|
+
body << "line break.\n"
|
20
|
+
body << "\n"
|
21
|
+
body << " * first item\n"
|
22
|
+
body << " * second item\n"
|
23
|
+
body << "\n"
|
24
|
+
body << " <div id=\"test\">\n"
|
25
|
+
body << " <p>Text</p>\n"
|
26
|
+
body << " </div>\n"
|
27
|
+
body << "\n"
|
28
|
+
body << "A third paragraph."
|
29
|
+
|
30
|
+
@cleaner.clean_value(body).should eq body
|
31
|
+
end
|
32
|
+
|
33
|
+
it "empties string full of spaces" do
|
34
|
+
[
|
35
|
+
"",
|
36
|
+
" ",
|
37
|
+
"\t",
|
38
|
+
"\n",
|
39
|
+
" \t\n \t\n \t\n \t\n",
|
40
|
+
].each do |title|
|
41
|
+
@cleaner.clean_value(title).should eq ""
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it "cleans repeted spaces" do
|
46
|
+
@cleaner.clean_value("Lorem ipsum \ndolor sit amet.").should eq "Lorem ipsum\ndolor sit amet."
|
47
|
+
@cleaner.clean_value("Lorem \t ipsum \t \ndolor \t sit \t amet.").should eq "Lorem ipsum\ndolor sit amet."
|
48
|
+
end
|
49
|
+
|
50
|
+
context "considering the spaces in the beggining of lines" do
|
51
|
+
it "preserves them" do
|
52
|
+
@cleaner.clean_value("Lorem ipsum\n dolor sit amet.").should eq "Lorem ipsum\n dolor sit amet."
|
53
|
+
end
|
54
|
+
it "clears line full of spaces" do
|
55
|
+
@cleaner.clean_value("Lorem ipsum \n \n dolor sit amet.").should eq "Lorem ipsum\n\n dolor sit amet."
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it "keeps two max succeeding new line" do
|
60
|
+
@cleaner.clean_value("Lorem ipsum\n\n\ndolor sit amet.").should eq "Lorem ipsum\n\ndolor sit amet."
|
61
|
+
@cleaner.clean_value("Lorem ipsum\n\n\n\ndolor sit amet.").should eq "Lorem ipsum\n\ndolor sit amet."
|
62
|
+
@cleaner.clean_value("Lorem ipsum\n \n \n \ndolor sit amet.").should eq "Lorem ipsum\n\ndolor sit amet."
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe ActiveCleaner::StringCleaner do
|
5
|
+
|
6
|
+
before do
|
7
|
+
@cleaner = ActiveCleaner::StringCleaner.new(:title)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#clean_value" do
|
11
|
+
|
12
|
+
it "doesn't touch legit value" do
|
13
|
+
@cleaner.clean_value("A good title!").should eq "A good title!"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "empties string full of spaces" do
|
17
|
+
[
|
18
|
+
"",
|
19
|
+
" ",
|
20
|
+
"\t",
|
21
|
+
"\n",
|
22
|
+
" \t\n \t\n \t\n \t\n",
|
23
|
+
].each do |title|
|
24
|
+
@cleaner.clean_value(title).should eq ""
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it "cleans leading and trailing spaces" do
|
29
|
+
@cleaner.clean_value(" A good title! ").should eq "A good title!"
|
30
|
+
end
|
31
|
+
it "cleans leading and trailing tabs" do
|
32
|
+
@cleaner.clean_value("\tA good title!\t").should eq "A good title!"
|
33
|
+
end
|
34
|
+
it "cleans leading and trailing lines" do
|
35
|
+
@cleaner.clean_value("\nA good title!\n").should eq "A good title!"
|
36
|
+
end
|
37
|
+
|
38
|
+
it "cleans repeted spaces" do
|
39
|
+
@cleaner.clean_value("A good title!").should eq "A good title!"
|
40
|
+
@cleaner.clean_value("A \n good \t title!").should eq "A good title!"
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe ActiveCleaner::TextCleaner do
|
5
|
+
|
6
|
+
before do
|
7
|
+
@cleaner = ActiveCleaner::TextCleaner.new(:text)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#clean_value" do
|
11
|
+
|
12
|
+
it "doesn't touch legit value" do
|
13
|
+
[
|
14
|
+
"Lorem ipsum dolor sit amet.",
|
15
|
+
"Lorem ipsum\ndolor sit amet.",
|
16
|
+
"Lorem ipsum\n\ndolor sit amet.",
|
17
|
+
].each do |text|
|
18
|
+
@cleaner.clean_value(text).should eq text
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "empties string full of spaces" do
|
23
|
+
[
|
24
|
+
"",
|
25
|
+
" ",
|
26
|
+
"\t",
|
27
|
+
"\n",
|
28
|
+
" \t\n \t\n \t\n \t\n",
|
29
|
+
].each do |title|
|
30
|
+
@cleaner.clean_value(title).should eq ""
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it "cleans leading and trailing spaces" do
|
35
|
+
@cleaner.clean_value(" Lorem ipsum\ndolor sit amet. ").should eq "Lorem ipsum\ndolor sit amet."
|
36
|
+
end
|
37
|
+
it "cleans leading and trailing tabs" do
|
38
|
+
@cleaner.clean_value("\tLorem ipsum\ndolor sit amet.\t").should eq "Lorem ipsum\ndolor sit amet."
|
39
|
+
end
|
40
|
+
it "cleans leading and trailing lines" do
|
41
|
+
@cleaner.clean_value("\nLorem ipsum\ndolor sit amet.\n").should eq "Lorem ipsum\ndolor sit amet."
|
42
|
+
end
|
43
|
+
|
44
|
+
it "cleans repeted spaces" do
|
45
|
+
@cleaner.clean_value("Lorem ipsum \n dolor sit amet.").should eq "Lorem ipsum\ndolor sit amet."
|
46
|
+
@cleaner.clean_value("Lorem \t ipsum \t \n dolor \t sit \t amet.").should eq "Lorem ipsum\ndolor sit amet."
|
47
|
+
end
|
48
|
+
|
49
|
+
it "keeps two max succeeding new line" do
|
50
|
+
@cleaner.clean_value("Lorem ipsum\n\n\ndolor sit amet.").should eq "Lorem ipsum\n\ndolor sit amet."
|
51
|
+
@cleaner.clean_value("Lorem ipsum\n\n\n\ndolor sit amet.").should eq "Lorem ipsum\n\ndolor sit amet."
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: activecleaner
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Maxime Garcia
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-01-30 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
none: false
|
17
|
+
requirements:
|
18
|
+
- - ~>
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '3.1'
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
none: false
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.1'
|
27
|
+
prerelease: false
|
28
|
+
type: :runtime
|
29
|
+
name: activemodel
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
32
|
+
none: false
|
33
|
+
requirements:
|
34
|
+
- - ~>
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '3.1'
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ~>
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '3.1'
|
43
|
+
prerelease: false
|
44
|
+
type: :runtime
|
45
|
+
name: activesupport
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
requirement: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
49
|
+
requirements:
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ! '>='
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
prerelease: false
|
60
|
+
type: :development
|
61
|
+
name: rspec
|
62
|
+
description: ! ' ActiveCleaner is a set of helpers that helps you in cleaning user-typed
|
63
|
+
content in your ActiveModel depending models (ActiveRecord, Mongoid...)
|
64
|
+
|
65
|
+
'
|
66
|
+
email:
|
67
|
+
- maxime.garcia@free.fr
|
68
|
+
executables: []
|
69
|
+
extensions: []
|
70
|
+
extra_rdoc_files: []
|
71
|
+
files:
|
72
|
+
- README.md
|
73
|
+
- LICENSE
|
74
|
+
- lib/active_cleaner.rb
|
75
|
+
- lib/active_cleaner/markdown_cleaner.rb
|
76
|
+
- lib/active_cleaner/version.rb
|
77
|
+
- lib/active_cleaner/base_cleaner.rb
|
78
|
+
- lib/active_cleaner/helper_methods.rb
|
79
|
+
- lib/active_cleaner/string_cleaner.rb
|
80
|
+
- lib/active_cleaner/text_cleaner.rb
|
81
|
+
- lib/activecleaner.rb
|
82
|
+
- spec/lib/active_cleaner/string_cleaner_spec.rb
|
83
|
+
- spec/lib/active_cleaner/text_cleaner_spec.rb
|
84
|
+
- spec/lib/active_cleaner/markdown_cleaner_spec.rb
|
85
|
+
- spec/lib/active_cleaner_spec.rb
|
86
|
+
- spec/spec_helper.rb
|
87
|
+
- spec/cases/inherit_spec.rb
|
88
|
+
- spec/cases/simple_spec.rb
|
89
|
+
- spec/cases/nilify_spec.rb
|
90
|
+
homepage: http://github.com/maximeg/activecleaner
|
91
|
+
licenses: []
|
92
|
+
post_install_message:
|
93
|
+
rdoc_options: []
|
94
|
+
require_paths:
|
95
|
+
- lib
|
96
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
none: false
|
104
|
+
requirements:
|
105
|
+
- - ! '>='
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
requirements: []
|
109
|
+
rubyforge_project:
|
110
|
+
rubygems_version: 1.8.25
|
111
|
+
signing_key:
|
112
|
+
specification_version: 3
|
113
|
+
summary: Clean the fields in your models
|
114
|
+
test_files:
|
115
|
+
- spec/lib/active_cleaner/string_cleaner_spec.rb
|
116
|
+
- spec/lib/active_cleaner/text_cleaner_spec.rb
|
117
|
+
- spec/lib/active_cleaner/markdown_cleaner_spec.rb
|
118
|
+
- spec/lib/active_cleaner_spec.rb
|
119
|
+
- spec/spec_helper.rb
|
120
|
+
- spec/cases/inherit_spec.rb
|
121
|
+
- spec/cases/simple_spec.rb
|
122
|
+
- spec/cases/nilify_spec.rb
|