tiny_sweeper 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4b3312c9ca196aa0ccc80e866b5c972df40a55c7
4
+ data.tar.gz: 3f784d995ee4dbbda4555888bfb239581602a31d
5
+ SHA512:
6
+ metadata.gz: 308e7c5b89350405f4ca03af67c8468f51a444aa3c96a4e9a9b4e6bede4ed70764b8ea07f0bd951dcfc11d125c6fffaf0e05d451cf080cff6abae7a6376b4ac7
7
+ data.tar.gz: 804648e58f8c3b0d7a3cfaf8d186ada84033c13e026b0daf326b5660063237ceda8304111293af406f3870a3204f033487bac46c4b5160aac04ac7e1e97364b4
data/.gitignore ADDED
@@ -0,0 +1,34 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Specific to RubyMotion:
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+
17
+ ## Documentation cache and generated files:
18
+ /.yardoc/
19
+ /_yardoc/
20
+ /doc/
21
+ /rdoc/
22
+
23
+ ## Environment normalisation:
24
+ /.bundle/
25
+ /lib/bundler/man/
26
+
27
+ # for a library or gem, you might want to ignore these files since the code is
28
+ # intended to run in multiple environments; otherwise, check them in:
29
+ # Gemfile.lock
30
+ # .ruby-version
31
+ # .ruby-gemset
32
+
33
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
34
+ .rvmrc
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ tiny_sweeper
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby 2.2.0
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2
4
+ - 2.1
5
+ - 2.0
6
+ - 1.9
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rake'
4
+ gem 'rspec'
data/Gemfile.lock ADDED
@@ -0,0 +1,25 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.2.5)
5
+ rake (10.4.2)
6
+ rspec (3.2.0)
7
+ rspec-core (~> 3.2.0)
8
+ rspec-expectations (~> 3.2.0)
9
+ rspec-mocks (~> 3.2.0)
10
+ rspec-core (3.2.0)
11
+ rspec-support (~> 3.2.0)
12
+ rspec-expectations (3.2.0)
13
+ diff-lcs (>= 1.2.0, < 2.0)
14
+ rspec-support (~> 3.2.0)
15
+ rspec-mocks (3.2.0)
16
+ diff-lcs (>= 1.2.0, < 2.0)
17
+ rspec-support (~> 3.2.0)
18
+ rspec-support (3.2.0)
19
+
20
+ PLATFORMS
21
+ ruby
22
+
23
+ DEPENDENCIES
24
+ rake
25
+ rspec
data/README.md ADDED
@@ -0,0 +1,105 @@
1
+ # TinySweeper
2
+
3
+ TinySweeper keeps your objects tidy!
4
+
5
+ It's a handy way to clean attributes on your Rails models, though it's independent of Rails, and can be used in any Ruby project. It gives you a light-weigt way to override your methods and declare how their inputs should be cleaned.
6
+
7
+ [![Build Status](https://travis-ci.org/ContinuityControl/tiny_sweeper.png?branch=master)](https://travis-ci.org/ContinuityControl/tiny_sweeper)
8
+ [![Code Climate](https://codeclimate.com/github/ContinuityControl/tiny_sweeper.png)](https://codeclimate.com/github/ContinuityControl/tiny_sweeper)
9
+
10
+ ## How Do I Use It?
11
+
12
+ ```ruby
13
+ class Sundae
14
+ attr_accessor :topping
15
+
16
+ include TinySweeper
17
+ sweep(:topping) { |topping| topping.strip.downcase }
18
+ end
19
+ ```
20
+
21
+ Now your Sundae toppings will be tidied up:
22
+
23
+ ```ruby
24
+ dessert = Sundae.new
25
+ dessert.topping = ' ButTTERscotCH '
26
+ dessert.topping #=> 'butterscotch'. Tidy!
27
+ ```
28
+
29
+ If you have an object with lots of attributes that need cleaning, you can do that, too:
30
+
31
+ ```ruby
32
+ dessert.sweep_up!
33
+ # or:
34
+ Sundae.sweep_up!(dessert)
35
+ ```
36
+
37
+ ### Future Ideas
38
+
39
+ Just spit-balling here...
40
+
41
+ It'd be nice to define sweep-ups for multiple fields.
42
+
43
+ If you often sweep up fields in the same way - say, squishing and nilifying blanks - it'd be nice to bundle that up in some way, so you don't have to repeat yourself. Something like this might be nice:
44
+
45
+ ```ruby
46
+ # in config/initializers/tiny_sweeper.rb, or similar:
47
+ TinySweeper.sweep_style(:squish_and_nil_blanks) { |value|
48
+ ...
49
+ }
50
+
51
+ class Sundae
52
+ sweep :topping, :squish_and_nil_blanks
53
+ end
54
+ ```
55
+
56
+ If TinySweeper doesn't know the sweeping technique you asked for, it would send it to the value in the typical symbol-to-proc fashion:
57
+
58
+ ```ruby
59
+ class Sundae
60
+ # This:
61
+ sweep :topping, :strip
62
+ # ...would be the same as this:
63
+ sweep :topping { |t| t.strip }
64
+ end
65
+ ```
66
+
67
+ ## How Does It Work?
68
+
69
+ You include the `TinySweeper` module in your class, and define some sweep-up rules on your class' attributes. It overrides your method, and defines a new method that cleans its input according to the sweep-up rule, and then calls the original method with the clean value.
70
+
71
+ "Isn't it better to generate a module for the new methods, and call `super`?"
72
+
73
+ Sure, but if you do that, the module's method is called *after* the original one. We want to clean the input *before* it gets to your method.
74
+
75
+ "Why not use `after_create` or `before_save` or `before_validate` callbacks?"
76
+
77
+ That's one approach, and it's used by [nilify_blanks](https://github.com/rubiety/nilify_blanks), so it's clearly workable.
78
+
79
+ But it means your data isn't cleaned until the callback runs; TinySweeper cleans your data as soon as it arrives.
80
+
81
+ Also, it requires rails, so you can't use it outside of rails.
82
+
83
+ ## Install It
84
+
85
+ The standard:
86
+
87
+ ```
88
+ $ gem install tiny_sweeper
89
+ ```
90
+
91
+ or add to your Gemfile:
92
+
93
+ ```
94
+ gem 'tiny_sweeper'
95
+ ```
96
+
97
+ ## Contributing
98
+
99
+ Help is always appreciated!
100
+
101
+ * Fork the repo.
102
+ * Make your changes in a topic branch. Don't forget your specs!
103
+ * Send a pull request.
104
+
105
+ Please don't update the .gemspec or VERSION; we'll coordinate that when we release an update.
data/Rakefile ADDED
File without changes
@@ -0,0 +1,56 @@
1
+ module TinySweeper
2
+ module ClassMethods
3
+ def sweep(field_name, &sweeper)
4
+ stop_if_attribute_does_not_exist!(field_name)
5
+ stop_if_we_have_seen_this_before!(field_name)
6
+
7
+ writer_method_name = writer_method_name(field_name)
8
+
9
+ alias_method "original #{writer_method_name}", writer_method_name
10
+
11
+ define_method(writer_method_name) do |value|
12
+ clean_value = sweeper.call(value)
13
+ send("original #{writer_method_name}", clean_value)
14
+ end
15
+ end
16
+
17
+ def sweep_up!(instance)
18
+ @swept_fields.each do |field|
19
+ instance.send("#{field}=", instance.send(field))
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def stop_if_attribute_does_not_exist!(field_name)
26
+ unless instance_methods.include?(writer_method_name(field_name))
27
+ raise "There is no method named #{field_name.inspect} to sweep up!"
28
+ end
29
+ end
30
+
31
+ def stop_if_we_have_seen_this_before!(field_name)
32
+ @swept_fields ||= []
33
+
34
+ if @swept_fields.include?(field_name)
35
+ raise "Don't sweep #{field_name} twice!"
36
+ end
37
+
38
+ @swept_fields << field_name
39
+ end
40
+
41
+ def writer_method_name(field_name)
42
+ "#{field_name}=".to_sym
43
+ end
44
+ end
45
+
46
+ def self.included(base)
47
+ base.send(:extend, ClassMethods)
48
+ end
49
+
50
+ def sweep_up!
51
+ self.class.sweep_up!(self)
52
+ end
53
+ end
54
+
55
+ # Do it on all fields, by default? Or be explicit?
56
+ # TODO: add EagerSweeper, which loops over attributes
@@ -0,0 +1,3 @@
1
+ module TinySweeper
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,91 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
4
+ # this file to always be loaded, without a need to explicitly require it in any
5
+ # files.
6
+ #
7
+ # Given that it is always loaded, you are encouraged to keep this file as
8
+ # light-weight as possible. Requiring heavyweight dependencies from this file
9
+ # will add to the boot time of your test suite on EVERY test run, even for an
10
+ # individual file that may not need all of that loaded. Instead, consider making
11
+ # a separate helper file that requires the additional dependencies and performs
12
+ # the additional setup, and require it from the spec files that actually need
13
+ # it.
14
+ #
15
+ # The `.rspec` file also contains a few flags that are not defaults but that
16
+ # users commonly want.
17
+ #
18
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
19
+ RSpec.configure do |config|
20
+ # rspec-expectations config goes here. You can use an alternate
21
+ # assertion/expectation library such as wrong or the stdlib/minitest
22
+ # assertions if you prefer.
23
+ config.expect_with :rspec do |expectations|
24
+ # This option will default to `true` in RSpec 4. It makes the `description`
25
+ # and `failure_message` of custom matchers include text for helper methods
26
+ # defined using `chain`, e.g.:
27
+ # be_bigger_than(2).and_smaller_than(4).description
28
+ # # => "be bigger than 2 and smaller than 4"
29
+ # ...rather than:
30
+ # # => "be bigger than 2"
31
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
32
+ end
33
+
34
+ # rspec-mocks config goes here. You can use an alternate test double
35
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
36
+ config.mock_with :rspec do |mocks|
37
+ # Prevents you from mocking or stubbing a method that does not exist on
38
+ # a real object. This is generally recommended, and will default to
39
+ # `true` in RSpec 4.
40
+ mocks.verify_partial_doubles = true
41
+ end
42
+
43
+ # The settings below are suggested to provide a good initial experience
44
+ # with RSpec, but feel free to customize to your heart's content.
45
+ =begin
46
+ # These two settings work together to allow you to limit a spec run
47
+ # to individual examples or groups you care about by tagging them with
48
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
49
+ # get run.
50
+ config.filter_run :focus
51
+ config.run_all_when_everything_filtered = true
52
+
53
+ # Limits the available syntax to the non-monkey patched syntax that is
54
+ # recommended. For more details, see:
55
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
56
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
57
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
58
+ config.disable_monkey_patching!
59
+
60
+ # This setting enables warnings. It's recommended, but in some cases may
61
+ # be too noisy due to issues in dependencies.
62
+ config.warnings = true
63
+
64
+ # Many RSpec users commonly either run the entire suite or an individual
65
+ # file, and it's useful to allow more verbose output when running an
66
+ # individual spec file.
67
+ if config.files_to_run.one?
68
+ # Use the documentation formatter for detailed output,
69
+ # unless a formatter has already been configured
70
+ # (e.g. via a command-line flag).
71
+ config.default_formatter = 'doc'
72
+ end
73
+
74
+ # Print the 10 slowest examples and example groups at the
75
+ # end of the spec run, to help surface which specs are running
76
+ # particularly slow.
77
+ config.profile_examples = 10
78
+
79
+ # Run specs in random order to surface order dependencies. If you find an
80
+ # order dependency and want to debug it, you can fix the order by providing
81
+ # the seed, which is printed after each run.
82
+ # --seed 1234
83
+ config.order = :random
84
+
85
+ # Seed global randomization in this process using the `--seed` CLI option.
86
+ # Setting this allows you to use `--seed` to deterministically reproduce
87
+ # test failures related to randomization by passing the same `--seed` value
88
+ # as the one that triggered the failure.
89
+ Kernel.srand config.seed
90
+ =end
91
+ end
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+ require 'tiny_sweeper'
3
+
4
+ describe 'cleaning fields' do
5
+ class Contract
6
+ attr_accessor :name, :notes
7
+
8
+ include TinySweeper
9
+ sweep :notes, &:strip
10
+ sweep(:name) { |n| n.upcase }
11
+ end
12
+
13
+ it 'leaves some unfortunate method names, maybe?' do
14
+ contract = Contract.new
15
+ original_writers = contract.methods.grep(/^original /).sort
16
+ expect(original_writers).to eq([:"original name=", :"original notes="])
17
+ # NB: we're not saying this is GOOD, we're just noting it.
18
+ end
19
+
20
+ it 'strips notes' do
21
+ contract = Contract.new
22
+ contract.notes = ' needs stripping '
23
+ expect(contract.notes).to eq('needs stripping')
24
+ end
25
+
26
+ it 'upcases name' do
27
+ contract = Contract.new
28
+ contract.name = 'gonna shout it'
29
+ expect(contract.name).to eq('GONNA SHOUT IT')
30
+ end
31
+
32
+ describe 'sweeping up ALL the fields at once' do
33
+ let(:the_contract) {
34
+ Contract.new.tap do |c|
35
+ c.name = ' will be upcased '
36
+ c.notes = ' will be stripped '
37
+ end
38
+ }
39
+
40
+ it 'can clean itself' do
41
+ the_contract.sweep_up!
42
+ expect(the_contract.name).to eq ' WILL BE UPCASED '
43
+ expect(the_contract.notes).to eq 'will be stripped'
44
+ end
45
+
46
+ it 'can be cleaned from the class' do
47
+ Contract.sweep_up!(the_contract)
48
+ expect(the_contract.name).to eq ' WILL BE UPCASED '
49
+ expect(the_contract.notes).to eq 'will be stripped'
50
+ end
51
+ end
52
+
53
+ it 'will bark if you try to re-define a field twice' do
54
+ some_class = Class.new
55
+ some_class.send(:include, TinySweeper)
56
+ some_class.send(:attr_accessor, :name)
57
+ some_class.send(:sweep, :name, &:strip)
58
+
59
+ # Now the class is sweeping up name, awesome!
60
+ # What if we try to sweep it AGAIN?
61
+
62
+ expect {
63
+ some_class.send(:sweep, :name, &:upcase)
64
+ }.to raise_error
65
+ end
66
+
67
+ it "will bark if you sweep a method that doesn't exist" do
68
+ some_class = Class.new
69
+ some_class.send(:include, TinySweeper)
70
+ expect {
71
+ some_class.send(:sweep, :attribute, &:whatever)
72
+ }.to raise_error("There is no method named :attribute to sweep up!")
73
+ end
74
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'tiny_sweeper/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'tiny_sweeper'
8
+ s.version = TinySweeper::VERSION
9
+ s.date = Date.today.to_s
10
+
11
+ s.summary = "A tiny helper to clean your inputs"
12
+ s.description = "
13
+ Tiny Sweeper is a handy way to clean attributes on your Rails models,
14
+ though it's independent of Rails, and can be used in any Ruby project.
15
+ It gives you a light-weight way to override your methods and declare
16
+ how their inputs should be cleaned.
17
+ ".strip.gsub(/^\s*/, '')
18
+ s.homepage = 'https://github.com/ContinuityControl/tiny_sweeper'
19
+ s.license = 'ASL2'
20
+
21
+ s.authors = ["Dan Bernier"]
22
+ s.email = ['dbernier@continuity.net']
23
+
24
+ s.files = `git ls-files -z`.split("\x0")
25
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
26
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
27
+ s.require_paths = ["lib"]
28
+
29
+ s.add_development_dependency "bundler", "~> 1.5"
30
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tiny_sweeper
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Dan Bernier
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ description: |-
28
+ Tiny Sweeper is a handy way to clean attributes on your Rails models,
29
+ though it's independent of Rails, and can be used in any Ruby project.
30
+ It gives you a light-weight way to override your methods and declare
31
+ how their inputs should be cleaned.
32
+ email:
33
+ - dbernier@continuity.net
34
+ executables: []
35
+ extensions: []
36
+ extra_rdoc_files: []
37
+ files:
38
+ - ".gitignore"
39
+ - ".rspec"
40
+ - ".ruby-gemset"
41
+ - ".ruby-version"
42
+ - ".travis.yml"
43
+ - Gemfile
44
+ - Gemfile.lock
45
+ - README.md
46
+ - Rakefile
47
+ - lib/tiny_sweeper.rb
48
+ - lib/tiny_sweeper/version.rb
49
+ - spec/spec_helper.rb
50
+ - spec/tiny_sweeper_spec.rb
51
+ - tiny_sweeper.gemspec
52
+ homepage: https://github.com/ContinuityControl/tiny_sweeper
53
+ licenses:
54
+ - ASL2
55
+ metadata: {}
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubyforge_project:
72
+ rubygems_version: 2.4.5
73
+ signing_key:
74
+ specification_version: 4
75
+ summary: A tiny helper to clean your inputs
76
+ test_files:
77
+ - spec/spec_helper.rb
78
+ - spec/tiny_sweeper_spec.rb