attribrutal 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ *.DS_Store
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
19
+ tags
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,27 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ attribrutal (0.0.4)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.2.5)
10
+ rake (10.1.1)
11
+ rspec (2.14.1)
12
+ rspec-core (~> 2.14.0)
13
+ rspec-expectations (~> 2.14.0)
14
+ rspec-mocks (~> 2.14.0)
15
+ rspec-core (2.14.8)
16
+ rspec-expectations (2.14.5)
17
+ diff-lcs (>= 1.1.3, < 2.0)
18
+ rspec-mocks (2.14.6)
19
+
20
+ PLATFORMS
21
+ ruby
22
+
23
+ DEPENDENCIES
24
+ attribrutal!
25
+ bundler
26
+ rake
27
+ rspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Jens Norrgrann
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,57 @@
1
+ Attribrutal
2
+ ============
3
+
4
+ Lazily coerced attributes
5
+
6
+ ##Usage:
7
+
8
+ class MoreSpeed
9
+ include Attribrutal::Model
10
+ attribute :harder
11
+ attribute :better
12
+ attribute :faster
13
+ attribute :stronger
14
+ end
15
+
16
+ ##With coercion:
17
+
18
+ class MoreSpeed
19
+ include Attribrutal::Model
20
+ attribute :harder, Coercion::Integer
21
+ attribute :better, Coercion::String
22
+ attribute :faster, Coercion::Boolean
23
+ attribute :stronger, MyAwesomeCoercion
24
+ end
25
+
26
+ ##With defaults:
27
+
28
+ class MoreSpeed
29
+ include Attribrutal::Model
30
+ attribute :harder, Coercion::Integer, default: 10
31
+ attribute :better, Coercion::String, default: "better"
32
+ attribute :faster, Coercion::Boolean, default: true
33
+ attribute :stronger, MyAwesomeCoercion
34
+ end
35
+
36
+ ##Introspection
37
+
38
+ `MoreSpeed.attributes` return a hash of attribute names and their types
39
+
40
+ ##Assignment
41
+
42
+ `MoreSpeed.new harder: 30, better: "much"`
43
+
44
+ ##Getting at raw (uncoerced) attributes
45
+
46
+ `MoreSpeed.new.raw_attributes`
47
+
48
+ ##Getting at coerced attributes
49
+
50
+ `MoreSpeed.new.attributes`
51
+
52
+ ##Coercers
53
+
54
+ Implement your own, they should provide a class method `coerce` which
55
+ takes two arguments; a value and a default and return the value
56
+ coerced or the default, its all up to the coercer. You can implement
57
+ any kind of additional meta information on the type.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'attribrutal/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'attribrutal'
8
+ spec.version = Attribrutal::VERSION
9
+ spec.date = '2014-03-17'
10
+ spec.summary = "Lazy attribute coercion"
11
+ spec.description = ""
12
+ spec.authors = ["Bukowskis"]
13
+ spec.email = ''
14
+ spec.homepage = ''
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files`.split($/) - ['.travis.yml']
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency('bundler')
22
+ spec.add_development_dependency('rake')
23
+ spec.add_development_dependency('rspec')
24
+ end
@@ -0,0 +1,33 @@
1
+ module Coercer
2
+
3
+ class Boolean
4
+ def self.coerce(arg, default = nil)
5
+ if arg == true
6
+ true
7
+ else
8
+ false
9
+ end
10
+ end
11
+ end
12
+
13
+ class Integer
14
+ def self.coerce(arg, default = nil)
15
+ if arg.nil?
16
+ default
17
+ else
18
+ Integer(arg)
19
+ end
20
+ end
21
+ end
22
+
23
+ class String
24
+ def self.coerce(arg, default = nil)
25
+ if arg.nil?
26
+ default
27
+ else
28
+ String(arg)
29
+ end
30
+ end
31
+ end
32
+
33
+ end
@@ -0,0 +1,58 @@
1
+ module Attribrutal
2
+
3
+ module Model
4
+
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ end
8
+
9
+ def initialize( attrs = {} )
10
+ @attributes = attrs
11
+ end
12
+
13
+ def raw_attributes
14
+ self.class.instance_variable_get("@attributes").keys.inject(Hash.new) do |attributes, attribute|
15
+ attributes[attribute] = @attributes[attribute]
16
+ attributes
17
+ end
18
+ end
19
+
20
+ def attributes
21
+ self.class.instance_variable_get("@attributes").keys.inject(Hash.new) do |attributes, attribute|
22
+ attributes[attribute] = self.send(attribute)
23
+ attributes
24
+ end
25
+ end
26
+
27
+ module ClassMethods
28
+
29
+ def attribute (sym, coercer=nil, attrs = {})
30
+
31
+ define_method(sym) do
32
+ if coercer
33
+ coercer.send(:coerce, @attributes[sym], attrs[:default])
34
+ else
35
+ @attributes[sym] || default
36
+ end
37
+ end
38
+
39
+ define_method("#{sym}=".to_sym) do |value|
40
+ @attributes[sym] = value
41
+ end
42
+
43
+ if @attributes
44
+ @attributes.merge!({ sym => coercer })
45
+ else
46
+ @attributes = { sym => coercer }
47
+ end
48
+ end
49
+
50
+ def attributes
51
+ @attributes
52
+ end
53
+
54
+ end
55
+
56
+ end
57
+
58
+ end
@@ -0,0 +1,3 @@
1
+ module Attribrutal
2
+ VERSION = "0.0.4"
3
+ end
@@ -0,0 +1,6 @@
1
+ require "attribrutal/version"
2
+ require "attribrutal/model.rb"
3
+ require "attribrutal/coercion.rb"
4
+
5
+ module Attribrutal
6
+ end
@@ -0,0 +1,55 @@
1
+ require "spec_helper"
2
+
3
+ describe "Attribrutal#attributes" do
4
+
5
+ let (:bar) { Bar.new foo: nil, bar: 10, baz: { alpha: 10, beta: "20" } }
6
+ let (:bar_with_defaults) { Bar.new }
7
+
8
+ it "records defined attributes" do
9
+ Bar.attributes.keys.should == [:foo, :bar, :baz]
10
+ end
11
+
12
+ it "records defined attribute types" do
13
+ Bar.attributes.values.should == [Coercer::Boolean, Coercer::String, Coercer::Baz]
14
+ end
15
+
16
+ it "supports mass assignment" do
17
+ bar.raw_attributes.values.should == [nil, 10, { alpha: 10, beta: "20" }]
18
+ bar.attributes[:foo].should == false
19
+ bar.attributes[:bar].should == "10"
20
+ bar.attributes[:baz].alpha.should == 10
21
+ bar.attributes[:baz].beta.should == 20
22
+ end
23
+
24
+ it "performs coercion" do
25
+ attributes = bar.attributes
26
+ attributes[:foo].should == false
27
+ attributes[:bar].should == "10"
28
+ end
29
+
30
+ it "supports recursive coercion" do
31
+ attributes = bar.attributes
32
+ attributes[:baz].alpha.should == 10
33
+ attributes[:baz].beta.should == 20
34
+ end
35
+
36
+ it "supports defaults" do
37
+ bar_with_defaults.bar.should == "bar"
38
+ bar_with_defaults.baz.class.should == Baz
39
+ bar_with_defaults.baz.alpha.should == 50
40
+ bar_with_defaults.baz.beta.should == 100
41
+ end
42
+
43
+ it "is fast enough" do
44
+ initialization_time = 1000 * Benchmark.realtime do
45
+ 10_000.times { Bar.new }
46
+ end
47
+ initialization_time.should < 5
48
+
49
+ coercion_time = 1000 * Benchmark.realtime do
50
+ 10_000.times { Bar.new foo: nil, bar: 10, baz: { alpha: "1", beta: "2" } }
51
+ end
52
+ coercion_time.should < 50
53
+ end
54
+
55
+ end
@@ -0,0 +1,8 @@
1
+ $LOAD_PATH.unshift File.expand_path('../support/models', __FILE__)
2
+
3
+ require 'attribrutal'
4
+ require 'benchmark'
5
+
6
+ require 'coercer'
7
+ require 'baz'
8
+ require 'bar'
@@ -0,0 +1,6 @@
1
+ class Bar
2
+ include Attribrutal::Model
3
+ attribute :foo, Coercer::Boolean
4
+ attribute :bar, Coercer::String, default: "bar"
5
+ attribute :baz, Coercer::Baz, default: lambda { ::Baz.new alpha: 50, beta: 100 }
6
+ end
@@ -0,0 +1,5 @@
1
+ class Baz
2
+ include Attribrutal::Model
3
+ attribute :alpha, Coercer::Integer, default: 1
4
+ attribute :beta, Coercer::Integer, default: 2
5
+ end
@@ -0,0 +1,13 @@
1
+ module Coercer
2
+
3
+ class Baz
4
+ def self.coerce(arg, default = nil)
5
+ if arg.nil?
6
+ default.lambda? ? default.call : default
7
+ else
8
+ ::Baz.new(arg)
9
+ end
10
+ end
11
+ end
12
+
13
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: attribrutal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -64,7 +64,23 @@ email: ''
64
64
  executables: []
65
65
  extensions: []
66
66
  extra_rdoc_files: []
67
- files: []
67
+ files:
68
+ - .gitignore
69
+ - Gemfile
70
+ - Gemfile.lock
71
+ - LICENSE.txt
72
+ - README.md
73
+ - Rakefile
74
+ - attribrutal.gemspec
75
+ - lib/attribrutal.rb
76
+ - lib/attribrutal/coercion.rb
77
+ - lib/attribrutal/model.rb
78
+ - lib/attribrutal/version.rb
79
+ - spec/attribrutal_spec.rb
80
+ - spec/spec_helper.rb
81
+ - spec/support/models/bar.rb
82
+ - spec/support/models/baz.rb
83
+ - spec/support/models/coercer.rb
68
84
  homepage: ''
69
85
  licenses:
70
86
  - MIT
@@ -80,7 +96,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
80
96
  version: '0'
81
97
  segments:
82
98
  - 0
83
- hash: -1455837332816569125
99
+ hash: 1547668724170686462
84
100
  required_rubygems_version: !ruby/object:Gem::Requirement
85
101
  none: false
86
102
  requirements:
@@ -89,11 +105,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
89
105
  version: '0'
90
106
  segments:
91
107
  - 0
92
- hash: -1455837332816569125
108
+ hash: 1547668724170686462
93
109
  requirements: []
94
110
  rubyforge_project:
95
111
  rubygems_version: 1.8.23
96
112
  signing_key:
97
113
  specification_version: 3
98
114
  summary: Lazy attribute coercion
99
- test_files: []
115
+ test_files:
116
+ - spec/attribrutal_spec.rb
117
+ - spec/spec_helper.rb
118
+ - spec/support/models/bar.rb
119
+ - spec/support/models/baz.rb
120
+ - spec/support/models/coercer.rb