disposable 0.0.9 → 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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -5
  3. data/CHANGES.md +4 -0
  4. data/Gemfile +1 -1
  5. data/README.md +154 -1
  6. data/database.sqlite3 +0 -0
  7. data/disposable.gemspec +7 -7
  8. data/gemfiles/Gemfile.rails-3.0.lock +10 -8
  9. data/gemfiles/Gemfile.rails-3.2.lock +9 -7
  10. data/gemfiles/Gemfile.rails-4.0.lock +9 -7
  11. data/gemfiles/Gemfile.rails-4.1.lock +10 -8
  12. data/lib/disposable.rb +6 -7
  13. data/lib/disposable/callback.rb +174 -0
  14. data/lib/disposable/composition.rb +21 -58
  15. data/lib/disposable/expose.rb +49 -0
  16. data/lib/disposable/twin.rb +85 -38
  17. data/lib/disposable/twin/builder.rb +12 -30
  18. data/lib/disposable/twin/changed.rb +50 -0
  19. data/lib/disposable/twin/collection.rb +95 -0
  20. data/lib/disposable/twin/composition.rb +43 -15
  21. data/lib/disposable/twin/option.rb +1 -1
  22. data/lib/disposable/twin/persisted.rb +20 -0
  23. data/lib/disposable/twin/property_processor.rb +29 -0
  24. data/lib/disposable/twin/representer.rb +42 -14
  25. data/lib/disposable/twin/save.rb +19 -34
  26. data/lib/disposable/twin/schema.rb +31 -0
  27. data/lib/disposable/twin/setup.rb +38 -0
  28. data/lib/disposable/twin/sync.rb +114 -0
  29. data/lib/disposable/version.rb +1 -1
  30. data/test/api_semantics_test.rb +263 -0
  31. data/test/callback_group_test.rb +222 -0
  32. data/test/callbacks_test.rb +450 -0
  33. data/test/example.rb +40 -0
  34. data/test/expose_test.rb +92 -0
  35. data/test/persisted_test.rb +101 -0
  36. data/test/test_helper.rb +64 -0
  37. data/test/twin/benchmarking.rb +33 -0
  38. data/test/twin/builder_test.rb +32 -0
  39. data/test/twin/changed_test.rb +108 -0
  40. data/test/twin/collection_test.rb +223 -0
  41. data/test/twin/composition_test.rb +56 -25
  42. data/test/twin/expose_test.rb +73 -0
  43. data/test/twin/feature_test.rb +61 -0
  44. data/test/twin/from_test.rb +37 -0
  45. data/test/twin/inherit_test.rb +57 -0
  46. data/test/twin/option_test.rb +27 -0
  47. data/test/twin/readable_test.rb +57 -0
  48. data/test/twin/save_test.rb +192 -0
  49. data/test/twin/schema_test.rb +69 -0
  50. data/test/twin/setup_test.rb +139 -0
  51. data/test/twin/skip_unchanged_test.rb +64 -0
  52. data/test/twin/struct_test.rb +168 -0
  53. data/test/twin/sync_option_test.rb +228 -0
  54. data/test/twin/sync_test.rb +128 -0
  55. data/test/twin/twin_test.rb +49 -128
  56. data/test/twin/writeable_test.rb +56 -0
  57. metadata +106 -20
  58. data/STUFF +0 -4
  59. data/lib/disposable/twin/finders.rb +0 -29
  60. data/lib/disposable/twin/new.rb +0 -30
  61. data/lib/disposable/twin/save_.rb +0 -21
  62. data/test/composition_test.rb +0 -102
data/STUFF DELETED
@@ -1,4 +0,0 @@
1
- USE CASE:
2
-
3
- <% client.invoices.outstanding.each do |invoice| %>
4
- <%= link_to invoice.invoice_number, {:controller => "party", :action => "invoice_show", :id => invoice.id, :entity_instance_id => client.party, :entity_type_id => EntityType::PARTY}, :onclick => "event.cancelBubble=true;" %> <%= number_to_currency(invoice.balance_out)
@@ -1,29 +0,0 @@
1
- module Disposable::Twin::Finders
2
- def find(*args)
3
- finders.find(*args)
4
- end
5
-
6
- # Use Song::Twin.finders.where(..) or whatever finder/scope is defined in the model.
7
- # It will return each model wrapped in a Twin.
8
- def finders
9
- FinderBuilder.new(self, _model)
10
- end
11
-
12
- class FinderBuilder
13
- def initialize(*args)
14
- @twin_class, @model_class = *args
15
- end
16
-
17
- private
18
- def method_missing(*args, &block)
19
- models = execute(*args, &block)
20
-
21
- return @twin_class.new(models) unless models.respond_to?(:each) # sorry for all the magic, but that's how ActiveRecord works.
22
- models.collect { |mdl| @twin_class.new(mdl) }
23
- end
24
-
25
- def execute(*args, &block)
26
- @model_class.send(*args, &block)
27
- end
28
- end
29
- end
@@ -1,30 +0,0 @@
1
- module Disposable
2
- class Twin
3
- # transform incoming model into twin API hash.
4
- def self.new_representer
5
- representer = Class.new(representer_class) # inherit configuration
6
-
7
- # wrap incoming nested model in its Twin.
8
- representer.representable_attrs.
9
- find_all { |attr| attr[:twin] }.
10
- each { |attr| attr.merge!(
11
- :prepare => lambda { |object, args|
12
- if twin = args.user_options[:object_map][object]
13
- twin
14
- else
15
- args.binding[:twin].evaluate(nil).new(object, args.user_options[:object_map])
16
- end
17
- }) }
18
-
19
- # song_title => model.title
20
- representer.representable_attrs.each do |attr|
21
- attr.merge!(
22
- :getter => lambda { |args|
23
- args.represented.send("#{args.binding[:private_name]}") }, # DISCUSS: can't we do that with representable's mechanics?
24
- )
25
- end
26
-
27
- representer
28
- end
29
- end
30
- end
@@ -1,21 +0,0 @@
1
- module Disposable
2
- class Twin
3
- # hash for #update_attributes (model API): {title: "Future World", album: <Album>}
4
- def self.save_representer
5
- # TODO: do that only at compile-time!
6
- save = Class.new(write_representer) # inherit configuration
7
- save.representable_attrs.
8
- find_all { |attr| attr[:twin] }.
9
- each { |attr| attr.merge!(
10
- :representable => true,
11
- :serialize => lambda { |obj, args| obj.send(:model) }) }
12
-
13
- save.representable_attrs.each do |attr|
14
- attr.merge!(:as => attr[:private_name])
15
- end
16
-
17
- save
18
- end
19
-
20
- end
21
- end
@@ -1,102 +0,0 @@
1
- require 'test_helper'
2
-
3
- class CompositionTest < MiniTest::Spec
4
- module Model
5
- Band = Struct.new(:id, :title)
6
- Album = Struct.new(:id, :name, :album)
7
- end
8
-
9
- module Twin
10
- class Album #< Disposable::Twin
11
- include Disposable::Composition
12
-
13
- map( {:album => [[:id], [:name], [:album]],
14
- :band => [[:id, :band_id], [:title]]
15
- } )
16
- end
17
- end
18
-
19
- let (:band) { Model::Band.new(1, "Frenzal Rhomb") }
20
- let (:album) { Model::Album.new(2, "Dick Sandwich", "For the Term of Their Unnatural Lives") }
21
- subject { Twin::Album.new(:album => album, :band => band) }
22
-
23
- describe "readers" do
24
- it { subject.id.must_equal 2 }
25
- it { subject.band_id.must_equal 1 }
26
- it { subject.name.must_equal "Dick Sandwich" }
27
- it { subject.album.must_equal "For the Term of Their Unnatural Lives" }
28
- it { subject.title.must_equal "Frenzal Rhomb" }
29
- end
30
-
31
-
32
- describe "writers" do
33
- before do
34
- subject.id = 3
35
- subject.band_id = 4
36
- subject.name = "Eclipse"
37
- subject.title = "Yngwie J. Malmsteen"
38
- subject.album = "Best Of"
39
- end
40
-
41
- it { subject.id.must_equal 3 }
42
- it { album.id.must_equal 3 }
43
- it { subject.band_id.must_equal 4 }
44
- it { band.id.must_equal 4 }
45
- it { subject.name.must_equal "Eclipse" }
46
- it { subject.title.must_equal "Yngwie J. Malmsteen" }
47
- it { album.name.must_equal "Eclipse" }
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" }
51
- end
52
- # it { subject.save }
53
-
54
- it "raises when non-mapped property" do
55
- assert_raises NoMethodError do
56
- subject.raise_an_exception
57
- end
58
- end
59
-
60
-
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.
66
- end
67
-
68
-
69
- describe "#each" do
70
- it "what" do
71
- results = []
72
- subject.each { |mdl| results << mdl.object_id }
73
- results.must_equal([album.object_id, band.object_id])
74
- end
75
- end
76
-
77
-
78
- describe "#_models" do
79
- it { subject.send(:_models).must_equal([album, band]) }
80
- it { Twin::Album.new(:album => album).send(:_models).must_equal([album]) }
81
- end
82
-
83
-
84
- describe "@map" do
85
- let (:composition) {
86
- Class.new do
87
- include Disposable::Composition
88
-
89
- map( {:album => [["id"], [:name]],
90
- "band" => [[:id, "band_id"], [:title]]
91
- } )
92
- end
93
- }
94
-
95
- # yepp, a private test WITH interface violation, as this is still a semi-public concept.
96
- it { composition.instance_variable_get(:@map).must_equal({
97
- :id => {:method=>:id, :model=>:album},
98
- :name => {:method=>:name, :model=>:album},
99
- :band_id => {:method=>:id, :model=>:band},
100
- :title => {:method=>:title, :model=>:band}}) }
101
- end
102
- end