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 CHANGED
@@ -1,6 +1,47 @@
1
1
  # Liner
2
2
 
3
- TODO: Write a gem description
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
@@ -4,6 +4,7 @@ task default: [:test]
4
4
 
5
5
  task :test do
6
6
  $LOAD_PATH.unshift('lib', 'spec')
7
+ require './test/test_helper.rb'
7
8
  Dir.glob('./test/**/*_test.rb') { |f| require f }
8
9
  end
9
10
 
data/lib/ext/class.rb ADDED
@@ -0,0 +1,5 @@
1
+ Class.class_eval do
2
+ def liner(*keys)
3
+ Liner.apply self, *keys
4
+ end
5
+ end
data/lib/liner.rb CHANGED
@@ -1,88 +1,32 @@
1
- class Liner
2
-
3
- VERSION = '0.0.1'
4
-
5
- class << self
6
- def new(*args)
7
- self < Liner ? super(*args) : new_subclass(*args)
8
- end
9
-
10
- def new_subclass(*keys)
11
- Class.new(self) do |klass|
12
- self.table_keys = (table_keys + keys.map(&:to_sym)).uniq
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
- private :table_keys
15
+ end
53
16
 
54
- def [](key)
55
- @table[key.to_sym]
56
- end
17
+ def Liner.new(*keys)
18
+ apply Class.new, *keys
19
+ end
57
20
 
58
- def []=(key,value)
59
- key = key.to_sym
60
- if table_keys.include?(key)
61
- @table[key] = value
62
- else
63
- raise ArgumentError, "Invalid liner attribute: '#{key}'."
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,7 @@
1
+ module Liner
2
+ module Base
3
+ def initialize(hash)
4
+ self.liner = hash
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ module Liner
2
+ module Equalizable
3
+ def ==(other)
4
+ return false unless other.class == self.class
5
+ liner == other.liner
6
+ end
7
+
8
+ def eql?(other)
9
+ return false unless other.class == self.class
10
+ liner.eql?(other.liner)
11
+ end
12
+ end
13
+ end
@@ -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,9 @@
1
+ module Liner
2
+ module Inspectable
3
+ def inspect
4
+ attribute_string = liner.map{|k,v| "#{k}=#{v.inspect}"}.join(', ')
5
+ "#<#{self.class} #{attribute_string}>"
6
+ end
7
+ alias :to_s :inspect
8
+ end
9
+ 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
@@ -0,0 +1,3 @@
1
+ module Liner
2
+ VERSION = '0.1.0'
3
+ end
data/liner.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'liner'
4
+ require 'liner/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "liner"
@@ -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
- it "::new_subclass must create a new class" do
5
- Liner.new_subclass(:a).must_be :<, Liner
6
- end
7
-
8
- it "::new must create a new class" do
9
- Liner.new(:a).must_be :<, Liner
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 return false when hashes are not equal" do
45
- subject.wont_be :==, Beer.new(name: 'Natural Light')
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
- end
48
- describe "#eql?" do
49
- it "should return true when hashes are equal" do
50
- subject.must_be :eql?, Beer.new(name: 'Pabst')
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 return false when hashes are not equal" do
53
- subject.wont_be :eql?, Beer.new(name: 'Natural Light')
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
@@ -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.1
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: 2013-12-22 00:00:00.000000000 Z
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: