disposable 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3028d579eaa9e41a6d3591c069809c98940bd7a1
4
- data.tar.gz: 12371d78cdf1c2bfe046021f45ffb0a1dbd4ccff
3
+ metadata.gz: 9f223895880d3cf7e132a9fc7fe289d2364cda94
4
+ data.tar.gz: f6fb9b0b50ab1f76f6a76c233bc6a7b764d715c0
5
5
  SHA512:
6
- metadata.gz: 2af96f209c219622ac48b55d86798cd392fd83cb73e14463319d965c20a01824e4354ff5f09e9b71bddc21caeb64e369cb265478c77572226c1245297a7f25bc
7
- data.tar.gz: e58b5545c50a104ca16ae784cb48a2280dc60a407f35345dcccf78e867756380993826be1e6d4ce5f442475f0fd1311fddc4f2079f467cf5d1b774ce05b44c07
6
+ metadata.gz: b419406d81071ac149d0bb88a4b4165763b752be5530125ddb4a2165b05ffb704087cc5502d37bde78ef75b132bf49b101d9b7ec475ef3754904619f5039cae9
7
+ data.tar.gz: 8f18dd625473e5880a7a600698bb36eef37cf1791df67ed59e91c9f0179e168d16a32e201002afa8d3bbb85f75d426b88fb5c28f7958d19404d8a8b1878112a9
data/CHANGES.md ADDED
@@ -0,0 +1,3 @@
1
+ # 0.0.4
2
+
3
+ * Added `Composition#[]` to access contained models in favor of reader methods to models. The latter got removed. This allows mapping methods with the same name than the contained object.
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  why?
5
5
  because i want this to fuckin work: Wallpaper.find(51).update_attributes(enabled:false)
6
-
6
+ i want to see my fields when opening the class file, a la DataMapper.
7
7
 
8
8
  ## Twin
9
9
 
data/database.sqlite3 CHANGED
Binary file
@@ -2,6 +2,7 @@ require 'forwardable'
2
2
 
3
3
  module Disposable
4
4
  # Composition delegates accessors to models as per configuration.
5
+ #
5
6
  # Composition doesn't know anything but methods (readers and writers) to expose and the mappings to
6
7
  # the internal models. Optionally, it knows about renamings such as mapping `#song_id` to `song.id`.
7
8
  #
@@ -14,6 +15,8 @@ module Disposable
14
15
  # album = Album.new(cd: CD.find(1), band: Band.new)
15
16
  # album.id #=> 1
16
17
  # album.title = "Ten Foot Pole"
18
+ #
19
+ # It allows accessing the contained models using the `#[]` reader.
17
20
  module Composition
18
21
  def self.included(base)
19
22
  base.extend(Forwardable)
@@ -26,8 +29,6 @@ module Disposable
26
29
  @map = {}
27
30
 
28
31
  options.each do |mdl, meths|
29
- attr_reader mdl
30
-
31
32
  meths.each do |mtd| # [[:title], [:id, :song_id]]
32
33
  create_accessors(mdl, mtd)
33
34
  add_to_map(mdl, mtd)
@@ -37,8 +38,8 @@ module Disposable
37
38
 
38
39
  private
39
40
  def create_accessors(model, methods)
40
- def_instance_delegator model, *methods # reader
41
- def_instance_delegator model, *methods.map { |m| "#{m}=" } # writer
41
+ def_instance_delegator "@#{model}", *methods # reader
42
+ def_instance_delegator "@#{model}", *methods.map { |m| "#{m}=" } # writer
42
43
  end
43
44
 
44
45
  def add_to_map(model, methods)
@@ -58,12 +59,17 @@ module Disposable
58
59
  @_models = models.values
59
60
  end
60
61
 
62
+ # Allows accessing the contained models.
63
+ def [](name)
64
+ instance_variable_get(:"@#{name}")
65
+ end
66
+
61
67
  # Allows multiplexing method calls to all composed models.
62
68
  def each(&block)
63
69
  _models.each(&block)
64
70
  end
65
71
 
66
72
  private
67
- attr_reader:_models
73
+ attr_reader :_models
68
74
  end
69
75
  end
@@ -32,14 +32,18 @@ module Disposable
32
32
  end
33
33
 
34
34
  def self.property(name, options={}, &block)
35
- options[:public_name] = options.delete(:as) || name
35
+ options[:private_name] = options.delete(:as) || name
36
36
  options[:pass_options] = true
37
37
 
38
38
  representer_class.property(name, options, &block).tap do |definition|
39
- attr_accessor definition[:public_name]
39
+ attr_accessor name
40
40
  end
41
41
  end
42
42
 
43
+ def self.collection(name, options={}, &block)
44
+ property(name, options.merge(:collection => true), &block)
45
+ end
46
+
43
47
  def self.from(model) # TODO: private.
44
48
  new(model)
45
49
  end
@@ -64,7 +68,7 @@ module Disposable
64
68
  :serialize => lambda { |obj, args| obj.send(:model) }) }
65
69
 
66
70
  save.representable_attrs.each do |attr|
67
- attr.merge!(:as => attr.name)
71
+ attr.merge!(:as => attr[:private_name])
68
72
  end
69
73
 
70
74
  save
@@ -78,11 +82,13 @@ module Disposable
78
82
  representer.representable_attrs.
79
83
  find_all { |attr| attr[:twin] }.
80
84
  each { |attr| attr.merge!(
81
- :prepare => lambda { |object, args| args.binding[:twin].new(object) }) }
85
+ :prepare => lambda { |object, args| args.binding[:twin].call.new(object) }) }
82
86
 
83
87
  # song_title => model.title
84
88
  representer.representable_attrs.each do |attr|
85
- attr.merge!(:as => attr[:public_name])
89
+ attr.merge!(
90
+ :getter => lambda { |args| send("#{args.binding[:private_name]}") },
91
+ )
86
92
  end
87
93
 
88
94
  representer
@@ -91,16 +97,6 @@ module Disposable
91
97
  # read/write to twin using twin's API (e.g. #record= not #album=).
92
98
  def self.write_representer
93
99
  representer = Class.new(representer_class) # inherit configuration
94
- representer.representable_attrs.
95
- each { |attr| attr.merge!(
96
- # use the alias name (as:) when writing attributes in new.
97
- # DISCUSS: attr.name = public_name would be simpler.
98
- :as => attr[:public_name],
99
- :getter => lambda { |args| send("#{args.binding[:public_name]}") },
100
- :setter => lambda { |value, args| send("#{args.binding[:public_name]}=", value) }
101
- )}
102
-
103
- representer
104
100
  end
105
101
 
106
102
  # call save on all nested twins.
@@ -1,3 +1,3 @@
1
1
  module Disposable
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -3,27 +3,28 @@ require 'test_helper'
3
3
  class CompositionTest < MiniTest::Spec
4
4
  module Model
5
5
  Band = Struct.new(:id, :title,)
6
- Album = Struct.new(:id, :name)
6
+ Album = Struct.new(:id, :name, :album)
7
7
  end
8
8
 
9
9
  module Twin
10
10
  class Album #< Disposable::Twin
11
11
  include Disposable::Composition
12
12
 
13
- map( {:album => [[:id], [:name]],
13
+ map( {:album => [[:id], [:name], [:album]],
14
14
  :band => [[:id, :band_id], [:title]]
15
15
  } )
16
16
  end
17
17
  end
18
18
 
19
19
  let (:band) { Model::Band.new(1, "Frenzal Rhomb") }
20
- let (:album) { Model::Album.new(2, "Dick Sandwhich") }
20
+ let (:album) { Model::Album.new(2, "Dick Sandwich", "For the Term of Their Unnatural Lives") }
21
21
  subject { Twin::Album.new(:album => album, :band => band) }
22
22
 
23
23
  describe "readers" do
24
24
  it { subject.id.must_equal 2 }
25
25
  it { subject.band_id.must_equal 1 }
26
- it { subject.name.must_equal "Dick Sandwhich" }
26
+ it { subject.name.must_equal "Dick Sandwich" }
27
+ it { subject.album.must_equal "For the Term of Their Unnatural Lives" }
27
28
  it { subject.title.must_equal "Frenzal Rhomb" }
28
29
  end
29
30
 
@@ -34,6 +35,7 @@ class CompositionTest < MiniTest::Spec
34
35
  subject.band_id = 4
35
36
  subject.name = "Eclipse"
36
37
  subject.title = "Yngwie J. Malmsteen"
38
+ subject.album = "Best Of"
37
39
  end
38
40
 
39
41
  it { subject.id.must_equal 3 }
@@ -44,6 +46,8 @@ class CompositionTest < MiniTest::Spec
44
46
  it { subject.title.must_equal "Yngwie J. Malmsteen" }
45
47
  it { album.name.must_equal "Eclipse" }
46
48
  it { band.title.must_equal "Yngwie J. Malmsteen" }
49
+ it { subject.album.must_equal "Best Of" }
50
+ it { album.album.must_equal "Best Of" }
47
51
  end
48
52
  # it { subject.save }
49
53
 
@@ -54,9 +58,11 @@ class CompositionTest < MiniTest::Spec
54
58
  end
55
59
 
56
60
 
57
- describe "readers to models" do
58
- it { subject.album.object_id.must_equal album.object_id }
59
- it { subject.band.object_id.must_equal band.object_id }
61
+ describe "#[]" do
62
+ it { subject[:album].object_id.must_equal album.object_id }
63
+ it { subject[:band].object_id.must_equal band.object_id }
64
+
65
+ it { assert_raises( NoMethodError) { subject.song } } # no reader to contained model.
60
66
  end
61
67
 
62
68
 
@@ -109,15 +109,15 @@ class TwinActiveRecordAsTest < MiniTest::Spec
109
109
  module Twin
110
110
  class Album < Disposable::Twin
111
111
  property :id
112
- property :name, :as => :album_name
112
+ property :album_name, :as => :name
113
113
 
114
114
  model ::Album
115
115
  end
116
116
 
117
117
  class Song < Disposable::Twin
118
118
  property :id
119
- property :title, :as => :song_title
120
- property :album, :twin => Album, :as => :record
119
+ property :song_title, :as => :title
120
+ property :record, :twin => Album, :as => :album
121
121
 
122
122
  model ::Song
123
123
  end
@@ -4,14 +4,18 @@ require 'test_helper'
4
4
  class TwinTest < MiniTest::Spec
5
5
  module Model
6
6
  Song = Struct.new(:id, :title, :album)
7
- Album = Struct.new(:id, :name)
7
+ Album = Struct.new(:id, :name, :songs)
8
8
  end
9
9
 
10
10
 
11
11
  module Twin
12
+ class Song < Disposable::Twin
13
+ end
14
+
12
15
  class Album < Disposable::Twin
13
16
  property :id # DISCUSS: needed for #save.
14
17
  property :name
18
+ collection :songs, :twin => Song
15
19
 
16
20
  model Model::Album
17
21
  end
@@ -27,20 +31,25 @@ class TwinTest < MiniTest::Spec
27
31
 
28
32
 
29
33
  describe "::new" do # TODO: this creates a new model!
30
- subject { Twin::Song.new }
34
+ let(:album) { Twin::Album.new }
35
+ let (:song) { Twin::Song.new }
31
36
 
32
- it { subject.title.must_equal nil }
33
- it { subject.album.must_equal nil }
37
+ it { album.name.must_equal nil }
38
+ it { album.songs.must_equal nil }
39
+ it { song.title.must_equal nil }
40
+ it { song.album.must_equal nil }
34
41
  end
35
42
 
36
43
 
37
44
  describe "::new with arguments" do
38
- let (:album) { Twin::Album.new(:name => "30 Years") }
45
+ let (:talking) { Twin::Song.new("title" => "Talking") }
46
+ let (:album) { Twin::Album.new(:name => "30 Years", :songs => [talking]) }
39
47
  subject { Twin::Song.new("title" => "Broken", "album" => album) }
40
48
 
41
49
  it { subject.title.must_equal "Broken" }
42
50
  it { subject.album.must_equal album }
43
51
  it { subject.album.name.must_equal "30 Years" }
52
+ it { album.songs.must_equal [talking] }
44
53
  end
45
54
 
46
55
 
@@ -55,13 +64,14 @@ class TwinTest < MiniTest::Spec
55
64
  # DISCUSS: make ::from private.
56
65
  describe "::from" do
57
66
  let (:song) { Model::Song.new(1, "Broken", album) }
58
- let (:album) { Model::Album.new(2, "The Process Of Belief") }
67
+ let (:album) { Model::Album.new(2, "The Process Of Belief", [Model::Song.new(3, "Dr. Stein")]) }
59
68
 
60
69
  subject {Twin::Song.from(song) }
61
70
 
62
71
  it { subject.title.must_equal "Broken" }
63
72
  it { subject.album.must_be_kind_of Twin::Album }
64
73
  it { subject.album.name.must_equal album.name }
74
+ it { subject.album.songs.first.title.must_equal "Dr. Stein" } # TODO: more tests on collections and object identity (if we need that).
65
75
  end
66
76
  end
67
77
 
@@ -88,14 +98,14 @@ class TwinAsTest < MiniTest::Spec
88
98
 
89
99
  module Twin
90
100
  class Album < Disposable::Twin
91
- property :name, :as => :record_name
101
+ property :record_name, :as => :name
92
102
 
93
103
  model Model::Album
94
104
  end
95
105
 
96
106
  class Song < Disposable::Twin
97
- property :title, :as => :name
98
- property :album, :twin => Album, :as => :record
107
+ property :name, :as => :title
108
+ property :record, :twin => Album, :as => :album
99
109
 
100
110
  model Model::Song
101
111
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: disposable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sutterer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-30 00:00:00.000000000 Z
11
+ date: 2014-05-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: uber
@@ -117,6 +117,7 @@ extra_rdoc_files: []
117
117
  files:
118
118
  - ".gitignore"
119
119
  - ".travis.yml"
120
+ - CHANGES.md
120
121
  - Gemfile
121
122
  - LICENSE.txt
122
123
  - README.md