disposable 0.0.9 → 0.1.0

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