liner 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: