in_format 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,20 @@
1
+ Copyright 2012 Cyrus Farajpour
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.
@@ -0,0 +1,125 @@
1
+ # InFormat
2
+
3
+ Easily add custom getter and setter filters for attributes on ActiveRecord objects. These can be useful if you wish to scrub data before it hits your datastore and/or provide uniformity when reading.
4
+
5
+ ## Requirements
6
+
7
+ For Ruby 1.9.0 and greater. Tested with Rails 3.1+ using ActiveRecord. It should work with any ORM that provides a hash syntax for accessing attributes in Models (please let me know if you have success/failures with other ORMs).
8
+
9
+ ## Installation
10
+
11
+ Add the requirement to your Gemfile
12
+
13
+ `gem "in_format"`
14
+
15
+ That's it if using ActiveRecord. If using a different ORM you will need to `extend InFormat` on the models, add an initializer or shoehorn it in some other way.
16
+
17
+ ## Usage
18
+
19
+ Invoke `in_format`, `phone_format` or `ssn_format` in your Model for attributes you wish to process.
20
+
21
+ ### in_format
22
+
23
+ The `in_format` method is the most general and accepts a getter and/or a setter.
24
+
25
+ Under the hood these create setters/getters and process the value through the supplied Proc/lambda and set/read the value using the hash syntax (`self[:attribute_name]`).
26
+
27
+ There is an `use_accessor` option which will override getter/setter methods matching the attribute. This can be useful if you want to combine `in_format` with `attr_accessor` or gems like [attr_encrypted](https://github.com/shuber/attr_encrypted) (just be sure that the overridden methods exist before using `in_format`).
28
+
29
+ You can access the original getter by passing `true` to the new one (assuming you supplied a getter).
30
+
31
+ ```ruby
32
+ class MyModel < ActiveRecord::Base
33
+ in_format :name, setter: lambda {|v| v.upcase }, getter: lambda {|v| "Mrs. #{v}"}
34
+
35
+ attr_accessor :some_attribute
36
+ in_format :some_attribute, use_accessor: true, setter: -> v { "#{v}s"}, getter: -> v { "3 {v}"}
37
+ end
38
+ ```
39
+
40
+ <pre>
41
+ m = MyModel.new(name: "shirley")
42
+ m.name(true) #=> "SHIRLEY"
43
+ m.name #=> "Mrs. SHIRLEY"
44
+
45
+ m.some_attribute = "beer"
46
+ m.some_attribute(true) #=> "beers"
47
+ m.some_attribute #=> "3 beers"
48
+ </pre>
49
+
50
+ This example is contrived and a little dangerous, `MyModel.new(name: nil) #=> splode!`, but you can do a lot with getters/setters.
51
+
52
+ ### phone_format
53
+
54
+ `phone_format` uses `in_format` with some pre-defined getters and setters.
55
+
56
+ ```ruby
57
+ class MyModel < ActiveRecord::Base
58
+ phone_format :phone
59
+ phone_format :phone_without_getter, getter: false
60
+ end
61
+ ```
62
+
63
+ <pre>
64
+ m = MyModel.new(phone: "(213) 222-2222", phone_without_getter: "(213) 222-2222")
65
+ m.name(true) #=> "2132222222"
66
+ m.name #=> "222-222-2222"
67
+ m.phone_without_getter #=> "2132222222"
68
+ </pre>
69
+
70
+ You can supply your own getter or setter like `in_format` if the defaults don't match your needs or you can pass a getter or setter with `false` to exclude it.
71
+
72
+ ### ssn_format
73
+
74
+ `ssn_format` works much like `phone_format`, also accepts custom getters/setters.
75
+
76
+ ```ruby
77
+ class MyModel < ActiveRecord::Base
78
+ ssn_format :ssn
79
+ end
80
+ ```
81
+
82
+ or with `attr_encrypted`
83
+
84
+ ```ruby
85
+ class MyModel < ActiveRecord::Base
86
+ attr_encrypted :ssn # defined before call to ssn_format
87
+ ssn_format :ssn, use_accessor: true
88
+ end
89
+ ```
90
+
91
+ <pre>
92
+ m = MyModel.new(ssn: "123 45 6789")
93
+ m.name(true) #=> "123456789"
94
+ m.name #=> "123-45-6789"
95
+ </pre>
96
+
97
+ ## Reccomendations
98
+
99
+ If you have getters/setters you would like to re-use across many attributes or classes I would stick em all in a (well-tested) module and keep an eye out for edge cases. You can also use `in_format` as the base for your own custom methods like `phone_format`, etc.
100
+
101
+ ```ruby
102
+ module MyFormatters
103
+ CAPS = -> v { |v| v ? v.to_s.capitalize : "Generic Dog Name" }
104
+ NO_CATS = lambda do |v|
105
+ if v =~ /cat/
106
+ v.gsub("cat", "")
107
+ else
108
+ v
109
+ end
110
+ end
111
+ end
112
+
113
+ class MyModel < ActiveRecord::Base
114
+ in_format :dog_name, setter: MyFormatters::NO_CATS, getter: MyFormatters::CAPS
115
+ end
116
+ ```
117
+
118
+ ## Upcoming
119
+
120
+ Currently this is written specifically for ActiveRecord but I hope to make it compatible with more ORMs. In the meantime you can use the alias option and it should work with any ruby class.
121
+
122
+ ## License
123
+
124
+ * Freely distributable and licensed under the [MIT license](http://cfarajpour.mit-license.org/license.html).
125
+ * Copyright (c) 2012 Cyrus Farajpour (smoils@gmail.com) [![endorse](http://api.coderwall.com/smoil/endorsecount.png)](http://coderwall.com/smoil)
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'InFormat'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+
24
+ Bundler::GemHelper.install_tasks
25
+
26
+ require 'rake/testtask'
27
+
28
+ require 'rspec/core/rake_task'
29
+
30
+ RSpec::Core::RakeTask.new(:spec)
31
+ task :default => :spec
@@ -0,0 +1,7 @@
1
+ require "in_format/core"
2
+ require "in_format/formatters"
3
+
4
+ module InFormat
5
+ end
6
+
7
+ require "in_format/railtie" if defined?(Rails)
@@ -0,0 +1,42 @@
1
+ module InFormat
2
+
3
+ def in_format(attribute, opts = {})
4
+
5
+ if opts[:setter]
6
+ if opts[:use_accessor]
7
+ original_setter = self.instance_method("#{attribute}=")
8
+
9
+ define_method("#{attribute}=") do |value|
10
+ original_setter.bind(self).call(opts[:setter].call(value))
11
+ end
12
+ else
13
+ define_method("#{attribute}=") do |value|
14
+ self[attribute.to_sym] = opts[:setter].call(value)
15
+ end
16
+ end
17
+ end
18
+
19
+ if opts[:getter]
20
+ if opts[:use_accessor]
21
+ original_getter = self.instance_method(attribute)
22
+
23
+ define_method("#{attribute}") do |raw = false|
24
+ if raw
25
+ original_getter.bind(self).call
26
+ else
27
+ opts[:getter].call(original_getter.bind(self).call)
28
+ end
29
+ end
30
+ else
31
+ define_method("#{attribute}") do |raw = false|
32
+ if raw
33
+ self[attribute.to_sym]
34
+ else
35
+ opts[:getter].call(self[attribute.to_sym])
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ end
@@ -0,0 +1,2 @@
1
+ require "in_format/formatters/phone"
2
+ require "in_format/formatters/ssn"
@@ -0,0 +1,65 @@
1
+ module InFormat
2
+
3
+ def phone_format(attribute, opts = {})
4
+ opts[:setter] = Formatters::Phone::DEFAULT_SETTER unless opts.keys.include? :setter
5
+ opts[:getter] = Formatters::Phone::DEFAULT_GETTER unless opts.keys.include? :getter
6
+
7
+ in_format(attribute, opts)
8
+ end
9
+
10
+ module Formatters
11
+ module Phone
12
+
13
+ DEFAULT_SETTER = lambda { |value| value.to_s.gsub(/[^\d|x]/, "") }
14
+
15
+ DEFAULT_GETTER = lambda do |value|
16
+ if value =~ /^\d{10,13}(x\d+)?$/
17
+ num, ext = value.split("x")
18
+ opts = { extension: ext }
19
+ opts.merge!(country_code: num[0..-11]) if num.length > 10
20
+ fmt = number_to_phone(num[(-1 * [num.length, 10].min)..-1].to_i, opts).to_s
21
+ fmt.gsub(" x "," x").gsub("+","")
22
+ else
23
+ value
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ # this is a slightly modified version taken from Rails ActionView::Helpers::NumberHelper
30
+ # credit belongs to the many people who have worked on that project
31
+ # code is released under the MIT License, matching the license used for this project
32
+ def self.number_to_phone(number, options = {})
33
+ return unless number
34
+
35
+ begin
36
+ Float(number)
37
+ rescue ArgumentError, TypeError
38
+ raise InvalidNumberError, number
39
+ end if options[:raise]
40
+
41
+ number = number.to_s.strip
42
+ options = options.symbolize_keys
43
+ area_code = options[:area_code]
44
+ delimiter = options[:delimiter] || "-"
45
+ extension = options[:extension]
46
+ country_code = options[:country_code]
47
+
48
+ if area_code
49
+ number.gsub!(/(\d{1,3})(\d{3})(\d{4}$)/,"(\\1) \\2#{delimiter}\\3")
50
+ else
51
+ number.gsub!(/(\d{0,3})(\d{3})(\d{4})$/,"\\1#{delimiter}\\2#{delimiter}\\3")
52
+ number.slice!(0, 1) if number.starts_with?(delimiter) && !delimiter.blank?
53
+ end
54
+
55
+ str = []
56
+ str << "+#{country_code}#{delimiter}" unless country_code.blank?
57
+ str << number
58
+ str << " x #{extension}" unless extension.blank?
59
+ str.join
60
+ end
61
+
62
+ end
63
+ end
64
+
65
+ end
@@ -0,0 +1,26 @@
1
+ module InFormat
2
+
3
+ def ssn_format(attribute, opts = {})
4
+ opts[:setter] = Formatters::Ssn::DEFAULT_SETTER unless opts.keys.include? :setter
5
+ opts[:getter] = Formatters::Ssn::DEFAULT_GETTER unless opts.keys.include? :getter
6
+
7
+ in_format(attribute, opts)
8
+ end
9
+
10
+ module Formatters
11
+ module Ssn
12
+
13
+ DEFAULT_SETTER = lambda { |value| value.to_s.gsub(/[^\d]/, "") }
14
+
15
+ DEFAULT_GETTER = lambda do |value|
16
+ if value =~ /^\d{9}\z/
17
+ "#{value[0..2]}-#{value[3..4]}-#{value[5..8]}"
18
+ else
19
+ value
20
+ end
21
+ end
22
+
23
+ end
24
+ end
25
+
26
+ end
@@ -0,0 +1,13 @@
1
+ module InFormat
2
+ class Railtie < Rails::Railtie
3
+
4
+ initializer "in_format.initialize" do
5
+
6
+ ActiveSupport.on_load :active_record do
7
+ ActiveRecord::Base.extend(InFormat)
8
+ end
9
+
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module InFormat
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: in_format
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Cyrus Farajpour
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-18 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: &70199367255320 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '3'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70199367255320
25
+ - !ruby/object:Gem::Dependency
26
+ name: sqlite3
27
+ requirement: &70199367254520 !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: *70199367254520
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec-rails
38
+ requirement: &70199367253680 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 2.8.1
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70199367253680
47
+ - !ruby/object:Gem::Dependency
48
+ name: attr_encrypted
49
+ requirement: &70199367252600 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 1.2.0
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70199367252600
58
+ - !ruby/object:Gem::Dependency
59
+ name: wirble
60
+ requirement: &70199367251740 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70199367251740
69
+ - !ruby/object:Gem::Dependency
70
+ name: awesome_print
71
+ requirement: &70199367250460 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70199367250460
80
+ description: Easily add custom getter and setter filters for attributes.
81
+ email:
82
+ - smoils@gmail.com
83
+ executables: []
84
+ extensions: []
85
+ extra_rdoc_files: []
86
+ files:
87
+ - lib/in_format/core.rb
88
+ - lib/in_format/formatters/phone.rb
89
+ - lib/in_format/formatters/ssn.rb
90
+ - lib/in_format/formatters.rb
91
+ - lib/in_format/railtie.rb
92
+ - lib/in_format/version.rb
93
+ - lib/in_format.rb
94
+ - LICENSE.txt
95
+ - Rakefile
96
+ - README.md
97
+ homepage: https://github.com/smoil/in_format
98
+ licenses: []
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ! '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ segments:
110
+ - 0
111
+ hash: -1601762158341379008
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ segments:
119
+ - 0
120
+ hash: -1601762158341379008
121
+ requirements: []
122
+ rubyforge_project:
123
+ rubygems_version: 1.8.15
124
+ signing_key:
125
+ specification_version: 3
126
+ summary: Easily add custom getter and setter filters for attributes.
127
+ test_files: []