liner 0.0.1 → 0.1.0
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/README.md +42 -3
- data/Rakefile +1 -0
- data/lib/ext/class.rb +5 -0
- data/lib/liner.rb +25 -81
- data/lib/liner/base.rb +7 -0
- data/lib/liner/equalizable.rb +13 -0
- data/lib/liner/hashable.rb +30 -0
- data/lib/liner/inspectable.rb +9 -0
- data/lib/liner/serializable.rb +21 -0
- data/lib/liner/version.rb +3 -0
- data/liner.gemspec +1 -1
- data/test/liner/equalizable_test.rb +19 -0
- data/test/liner/hashable_test.rb +32 -0
- data/test/liner/inspectable_test.rb +9 -0
- data/test/liner_test.rb +18 -78
- data/test/test_helper.rb +15 -0
- metadata +17 -2
data/README.md
CHANGED
@@ -1,6 +1,47 @@
|
|
1
1
|
# Liner
|
2
2
|
|
3
|
-
|
3
|
+
Lay a liner for your basic Ruby classes. Basically, it's a solid foundation for a PORO (Plain Old Ruby Object). A Liner is something like a more flexible Struct or a less magical OpenStruct, with enhanced inheritability.
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
You can setup a Liner based class in any of these equivalent ways:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
Engine = Liner.new(:layout, :fuel)
|
11
|
+
```
|
12
|
+
```ruby
|
13
|
+
class Engine < Liner.new(:layout, :fuel)
|
14
|
+
end
|
15
|
+
```
|
16
|
+
```ruby
|
17
|
+
class Engine
|
18
|
+
liner :layout, :fuel
|
19
|
+
end
|
20
|
+
```
|
21
|
+
|
22
|
+
It comes with a hash based initializer and a nice inspector.
|
23
|
+
```ruby
|
24
|
+
e = Engine.new(layout: 'V8', fuel: "gasoline") # => #<Engine layout="V8", fuel="gasoline">
|
25
|
+
```
|
26
|
+
|
27
|
+
Attribute getters and setters are built in.
|
28
|
+
```ruby
|
29
|
+
e.fuel # => "gasoline"
|
30
|
+
e.fuel = "diesel" # => "diesel"
|
31
|
+
```
|
32
|
+
|
33
|
+
Attributes are accessible via hash-style lookup too.
|
34
|
+
```ruby
|
35
|
+
e[:layout] # => "V8"
|
36
|
+
e[:layout] = "V6" # => "V6"
|
37
|
+
e[:foo] = "Bar" # => ArgumentError: Invalid liner attribute: 'foo'
|
38
|
+
```
|
39
|
+
|
40
|
+
Equality methods are also availble.
|
41
|
+
```ruby
|
42
|
+
e.eql? Engine.new(layout: 'I4') # => false
|
43
|
+
e == Engine.new(layout: 'V6', fuel: 'diesel') # => true
|
44
|
+
```
|
4
45
|
|
5
46
|
## Installation
|
6
47
|
|
@@ -16,9 +57,7 @@ Or install it yourself as:
|
|
16
57
|
|
17
58
|
$ gem install liner
|
18
59
|
|
19
|
-
## Usage
|
20
60
|
|
21
|
-
TODO: Write usage instructions here
|
22
61
|
|
23
62
|
## Contributing
|
24
63
|
|
data/Rakefile
CHANGED
data/lib/ext/class.rb
ADDED
data/lib/liner.rb
CHANGED
@@ -1,88 +1,32 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def inherited(child)
|
17
|
-
child.table_keys = (child.table_keys + self.table_keys).uniq
|
18
|
-
end
|
19
|
-
|
20
|
-
def table_keys
|
21
|
-
@table_keys ||= []
|
1
|
+
require 'liner/version'
|
2
|
+
require 'liner/base'
|
3
|
+
require 'liner/hashable'
|
4
|
+
require 'liner/equalizable'
|
5
|
+
require 'liner/inspectable'
|
6
|
+
require 'liner/serializable'
|
7
|
+
require 'ext/class'
|
8
|
+
|
9
|
+
module Liner
|
10
|
+
def self.included(base)
|
11
|
+
[Base, Hashable, Equalizable, Inspectable, Serializable].each do |mod|
|
12
|
+
base.send :include, mod
|
22
13
|
end
|
23
|
-
protected :table_keys
|
24
|
-
|
25
|
-
def table_keys=(keys)
|
26
|
-
keys = keys.map(&:to_sym)
|
27
|
-
keys.each do |key|
|
28
|
-
define_method(key) do
|
29
|
-
self[key]
|
30
|
-
end
|
31
|
-
define_method("#{key}=") do |value|
|
32
|
-
self[key] = value
|
33
|
-
end
|
34
|
-
end
|
35
|
-
@table_keys = keys
|
36
|
-
end
|
37
|
-
protected :table_keys=
|
38
|
-
end
|
39
|
-
|
40
|
-
def initialize(hash=nil)
|
41
|
-
@table = table_keys.inject({}){ |h,k| h[k]=nil; h }
|
42
|
-
if hash
|
43
|
-
hash.each do |k,v|
|
44
|
-
self[k] = hash[k]
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def table_keys
|
50
|
-
self.class.send(:table_keys)
|
51
14
|
end
|
52
|
-
|
15
|
+
end
|
53
16
|
|
54
|
-
|
55
|
-
|
56
|
-
|
17
|
+
def Liner.new(*keys)
|
18
|
+
apply Class.new, *keys
|
19
|
+
end
|
57
20
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
21
|
+
def Liner.apply(base, *keys)
|
22
|
+
keys = keys.map(&:to_sym).uniq
|
23
|
+
base.class_eval do
|
24
|
+
define_method(:liner_keys){ keys }
|
25
|
+
include Liner
|
26
|
+
keys.each do |key|
|
27
|
+
define_method(key){ self[key] }
|
28
|
+
define_method("#{key}="){ |value| self[key] = value }
|
64
29
|
end
|
65
30
|
end
|
66
|
-
|
67
|
-
def to_h
|
68
|
-
@table.dup
|
69
|
-
end
|
70
|
-
|
71
|
-
attr_reader :table
|
72
|
-
protected :table
|
73
|
-
|
74
|
-
def ==(other)
|
75
|
-
return false unless other.class == self.class
|
76
|
-
@table == other.table
|
77
|
-
end
|
78
|
-
|
79
|
-
def eql?(other)
|
80
|
-
return false unless other.class == self.class
|
81
|
-
@table.eql?(other.table)
|
82
|
-
end
|
83
|
-
|
84
|
-
def inspect
|
85
|
-
attribute_string = @table.map{|k,v| "#{k}=#{v.inspect}"}.join(', ')
|
86
|
-
"#<#{self.class} #{attribute_string}>"
|
87
|
-
end
|
31
|
+
base
|
88
32
|
end
|
data/lib/liner/base.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
module Liner
|
2
|
+
module Hashable
|
3
|
+
|
4
|
+
def liner
|
5
|
+
@liner ||= liner_keys.inject({}) { |h,k| h[k]=nil; h }
|
6
|
+
end
|
7
|
+
|
8
|
+
def liner=(hash)
|
9
|
+
hash.each { |k,v| self[k] = hash[k] }
|
10
|
+
end
|
11
|
+
|
12
|
+
def [](key)
|
13
|
+
liner[key.to_sym]
|
14
|
+
end
|
15
|
+
|
16
|
+
def []=(key,value)
|
17
|
+
key = key.to_sym
|
18
|
+
if liner_keys.include?(key)
|
19
|
+
liner[key] = value
|
20
|
+
else
|
21
|
+
raise ArgumentError, "Invalid liner attribute: '#{key}'."
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_h
|
26
|
+
liner.dup
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Liner
|
2
|
+
module Serializable
|
3
|
+
def self.included(base)
|
4
|
+
base.extend(ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def json_create(o)
|
9
|
+
new o['liner']
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def as_json(*)
|
14
|
+
{ 'json_class' => self.class.name, 'liner' => liner }
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_json(*args)
|
18
|
+
as_json.to_json(*args)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/liner.gemspec
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
describe Liner::Equalizable do
|
2
|
+
subject { Pizza.new(crust: 'thin', sauce: 'tomato') }
|
3
|
+
describe "#==" do
|
4
|
+
it "should return true when hashes are equal" do
|
5
|
+
subject.must_be :==, Pizza.new(crust: 'thin', sauce: 'tomato')
|
6
|
+
end
|
7
|
+
it "should return false when hashes are not equal" do
|
8
|
+
subject.wont_be :==, Pizza.new(crust: 'thick', sauce: 'alfredo')
|
9
|
+
end
|
10
|
+
end
|
11
|
+
describe "#eql?" do
|
12
|
+
it "should return true when hashes are equal" do
|
13
|
+
subject.must_be :eql?, Pizza.new(crust: 'thin', sauce: 'tomato')
|
14
|
+
end
|
15
|
+
it "should return false when hashes are not equal" do
|
16
|
+
subject.wont_be :eql?, Pizza.new(crust: 'thick', sauce: 'alfredo')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
describe Liner::Hashable do
|
2
|
+
subject { Beer.new(hops: 'Cascade') }
|
3
|
+
|
4
|
+
it "#[] should read attributes" do
|
5
|
+
subject[:hops].must_equal "Cascade"
|
6
|
+
subject[:yeast].must_equal nil
|
7
|
+
end
|
8
|
+
|
9
|
+
it "#[]= should set attributes" do
|
10
|
+
subject[:yeast]= "Top Fermenting"
|
11
|
+
subject.yeast.must_equal "Top Fermenting"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "#[]= should not set invalid attributes" do
|
15
|
+
->{ subject[:foo] = 'bar' }.must_raise ArgumentError
|
16
|
+
end
|
17
|
+
|
18
|
+
it "liner should be a hash of attributes" do
|
19
|
+
subject.liner.must_equal({ hops: 'Cascade', yeast: nil })
|
20
|
+
end
|
21
|
+
|
22
|
+
it "liner= should set the attributes" do
|
23
|
+
hash = {hops: 'Columbus', yeast: 'Bottom Fermenting' }
|
24
|
+
subject.liner = hash
|
25
|
+
subject.liner.must_equal(hash)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "#to_h should return the attribute hash" do
|
29
|
+
subject.to_h.must_equal({ hops: 'Cascade', yeast: nil })
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
describe Liner::Inspectable do
|
2
|
+
subject { Burger.new(meat: 'turkey') }
|
3
|
+
it "#inspect must include all attributes" do
|
4
|
+
subject.inspect.must_equal '#<Burger bun=nil, meat="turkey", cheese=nil>'
|
5
|
+
end
|
6
|
+
it "#to_s must include all attributes" do
|
7
|
+
subject.to_s.must_equal '#<Burger bun=nil, meat="turkey", cheese=nil>'
|
8
|
+
end
|
9
|
+
end
|
data/test/liner_test.rb
CHANGED
@@ -1,85 +1,25 @@
|
|
1
|
-
require 'minitest/autorun'
|
2
|
-
|
3
1
|
describe Liner do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
class Beer < Liner.new(:name)
|
14
|
-
end
|
15
|
-
|
16
|
-
describe Beer do
|
17
|
-
subject { Beer.new(name: "Pabst") }
|
18
|
-
it "::new must create a new instance" do
|
19
|
-
subject.must_be_instance_of Beer
|
20
|
-
subject.must_be_kind_of Liner
|
21
|
-
end
|
22
|
-
|
23
|
-
it "#[] should read attributes" do
|
24
|
-
subject[:name].must_equal "Pabst"
|
25
|
-
end
|
26
|
-
|
27
|
-
it "#[]= should set attributes" do
|
28
|
-
subject[:name]= "High Life"
|
29
|
-
subject.name.must_equal "High Life"
|
30
|
-
end
|
31
|
-
|
32
|
-
it "#[]= should not set invalid attributes" do
|
33
|
-
->{ subject[:foo] = 'bar' }.must_raise ArgumentError
|
34
|
-
end
|
35
|
-
|
36
|
-
it "#inspect must include all attributes" do
|
37
|
-
subject.inspect.must_equal '#<Beer name="Pabst">'
|
38
|
-
end
|
39
|
-
|
40
|
-
describe "#==" do
|
41
|
-
it "should return true when hashes are equal" do
|
42
|
-
subject.must_be :==, Beer.new(name: 'Pabst')
|
2
|
+
describe :new do
|
3
|
+
let(:beer) { Beer.new(hops: 'columbus') }
|
4
|
+
let(:pizza) { Pizza.new(crust: 'thin') }
|
5
|
+
let(:burger){ Burger.new(bun: 'sesame') }
|
6
|
+
it "should create a new class" do
|
7
|
+
[Beer, Pizza, Burger].all?{|klass| klass.is_a? Class }
|
43
8
|
end
|
44
|
-
it "should
|
45
|
-
|
9
|
+
it "should define liner_keys" do
|
10
|
+
beer.liner_keys.must_equal [:hops, :yeast]
|
11
|
+
pizza.liner_keys.must_equal [:crust, :sauce]
|
12
|
+
burger.liner_keys.must_equal [:bun, :meat, :cheese]
|
46
13
|
end
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
14
|
+
it "should define attribute getters" do
|
15
|
+
beer.must_respond_to :hops
|
16
|
+
pizza.must_respond_to :sauce
|
17
|
+
burger.must_respond_to :meat
|
51
18
|
end
|
52
|
-
it "should
|
53
|
-
|
19
|
+
it "should define attribute setters" do
|
20
|
+
beer.must_respond_to :yeast=
|
21
|
+
pizza.must_respond_to :crust=
|
22
|
+
burger.must_respond_to :bun=
|
54
23
|
end
|
55
24
|
end
|
56
|
-
|
57
|
-
it "#to_h should return the table" do
|
58
|
-
subject.to_h.must_equal name: 'Pabst'
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
PaleAle = Beer.new_subclass(:hops)
|
63
|
-
describe PaleAle do
|
64
|
-
subject { PaleAle.new(name: "Sierra Nevada", hops: "Cascade") }
|
65
|
-
|
66
|
-
it "::new must create a new instance" do
|
67
|
-
subject.must_be_instance_of PaleAle
|
68
|
-
subject.must_be_kind_of Beer
|
69
|
-
subject.must_be_kind_of Liner
|
70
|
-
end
|
71
|
-
|
72
|
-
it "#name must get the name" do
|
73
|
-
subject.name.must_equal "Sierra Nevada"
|
74
|
-
end
|
75
|
-
|
76
|
-
it "#hops must get the hops" do
|
77
|
-
subject.hops.must_equal "Cascade"
|
78
|
-
end
|
79
|
-
|
80
|
-
it "#hops= must set the hops" do
|
81
|
-
subject.hops = nil
|
82
|
-
subject.hops.must_equal nil
|
83
|
-
end
|
84
|
-
|
85
25
|
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'minitest/pride'
|
3
|
+
require 'liner'
|
4
|
+
|
5
|
+
|
6
|
+
# create some dummy classes to test against with each of the supported usages.
|
7
|
+
|
8
|
+
Beer = Liner.new :hops, :yeast
|
9
|
+
|
10
|
+
class Pizza < Liner.new(:crust, :sauce)
|
11
|
+
end
|
12
|
+
|
13
|
+
class Burger
|
14
|
+
liner :bun, :meat, :cheese
|
15
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: liner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2014-01-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -71,9 +71,20 @@ files:
|
|
71
71
|
- LICENSE.txt
|
72
72
|
- README.md
|
73
73
|
- Rakefile
|
74
|
+
- lib/ext/class.rb
|
74
75
|
- lib/liner.rb
|
76
|
+
- lib/liner/base.rb
|
77
|
+
- lib/liner/equalizable.rb
|
78
|
+
- lib/liner/hashable.rb
|
79
|
+
- lib/liner/inspectable.rb
|
80
|
+
- lib/liner/serializable.rb
|
81
|
+
- lib/liner/version.rb
|
75
82
|
- liner.gemspec
|
83
|
+
- test/liner/equalizable_test.rb
|
84
|
+
- test/liner/hashable_test.rb
|
85
|
+
- test/liner/inspectable_test.rb
|
76
86
|
- test/liner_test.rb
|
87
|
+
- test/test_helper.rb
|
77
88
|
homepage: https://github.com/joshwlewis/liner
|
78
89
|
licenses:
|
79
90
|
- MIT
|
@@ -100,5 +111,9 @@ signing_key:
|
|
100
111
|
specification_version: 3
|
101
112
|
summary: A liner for Ruby objects. Add attribute, inspection, and equality methods.
|
102
113
|
test_files:
|
114
|
+
- test/liner/equalizable_test.rb
|
115
|
+
- test/liner/hashable_test.rb
|
116
|
+
- test/liner/inspectable_test.rb
|
103
117
|
- test/liner_test.rb
|
118
|
+
- test/test_helper.rb
|
104
119
|
has_rdoc:
|