trailblazer 2.0.7 → 2.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 (72) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.rubocop-https---raw-githubusercontent-com-trailblazer-meta-master-rubocop-yml +101 -0
  4. data/.rubocop.yml +20 -0
  5. data/.rubocop_todo.yml +556 -0
  6. data/.travis.yml +6 -10
  7. data/CHANGES.md +83 -1
  8. data/COMM-LICENSE +46 -75
  9. data/CONTRIBUTING.md +179 -0
  10. data/Gemfile +0 -27
  11. data/{LICENSE.txt → LICENSE} +4 -4
  12. data/README.md +39 -138
  13. data/Rakefile +2 -19
  14. data/lib/trailblazer.rb +3 -17
  15. data/lib/trailblazer/version.rb +3 -1
  16. data/test/test_helper.rb +12 -3
  17. data/trailblazer.gemspec +10 -14
  18. metadata +22 -147
  19. data/doc/Trb-The-Stack.png +0 -0
  20. data/doc/operation-2017.png +0 -0
  21. data/doc/trb.jpg +0 -0
  22. data/lib/trailblazer/dsl.rb +0 -47
  23. data/lib/trailblazer/operation/auto_inject.rb +0 -47
  24. data/lib/trailblazer/operation/callback.rb +0 -35
  25. data/lib/trailblazer/operation/contract.rb +0 -46
  26. data/lib/trailblazer/operation/guard.rb +0 -18
  27. data/lib/trailblazer/operation/model.rb +0 -60
  28. data/lib/trailblazer/operation/module.rb +0 -29
  29. data/lib/trailblazer/operation/nested.rb +0 -113
  30. data/lib/trailblazer/operation/persist.rb +0 -10
  31. data/lib/trailblazer/operation/policy.rb +0 -35
  32. data/lib/trailblazer/operation/procedural/contract.rb +0 -15
  33. data/lib/trailblazer/operation/procedural/validate.rb +0 -22
  34. data/lib/trailblazer/operation/pundit.rb +0 -38
  35. data/lib/trailblazer/operation/representer.rb +0 -31
  36. data/lib/trailblazer/operation/rescue.rb +0 -21
  37. data/lib/trailblazer/operation/test.rb +0 -17
  38. data/lib/trailblazer/operation/validate.rb +0 -68
  39. data/lib/trailblazer/operation/wrap.rb +0 -25
  40. data/test/docs/auto_inject_test.rb +0 -30
  41. data/test/docs/contract_test.rb +0 -525
  42. data/test/docs/dry_test.rb +0 -31
  43. data/test/docs/fast_test.rb +0 -164
  44. data/test/docs/guard_test.rb +0 -169
  45. data/test/docs/macro_test.rb +0 -36
  46. data/test/docs/model_test.rb +0 -75
  47. data/test/docs/nested_test.rb +0 -334
  48. data/test/docs/operation_test.rb +0 -408
  49. data/test/docs/policy_test.rb +0 -2
  50. data/test/docs/pundit_test.rb +0 -133
  51. data/test/docs/representer_test.rb +0 -268
  52. data/test/docs/rescue_test.rb +0 -154
  53. data/test/docs/wrap_test.rb +0 -183
  54. data/test/gemfiles/Gemfile.ruby-1.9 +0 -3
  55. data/test/gemfiles/Gemfile.ruby-2.0 +0 -12
  56. data/test/gemfiles/Gemfile.ruby-2.3 +0 -12
  57. data/test/module_test.rb +0 -100
  58. data/test/operation/callback_test.rb +0 -70
  59. data/test/operation/contract_test.rb +0 -420
  60. data/test/operation/dsl/callback_test.rb +0 -106
  61. data/test/operation/dsl/contract_test.rb +0 -294
  62. data/test/operation/dsl/representer_test.rb +0 -169
  63. data/test/operation/model_test.rb +0 -60
  64. data/test/operation/params_test.rb +0 -36
  65. data/test/operation/persist_test.rb +0 -44
  66. data/test/operation/pipedream_test.rb +0 -59
  67. data/test/operation/pipetree_test.rb +0 -104
  68. data/test/operation/present_test.rb +0 -24
  69. data/test/operation/pundit_test.rb +0 -104
  70. data/test/operation/representer_test.rb +0 -254
  71. data/test/operation/resolver_test.rb +0 -47
  72. data/test/operation_test.rb +0 -143
@@ -1,60 +0,0 @@
1
- require "test_helper"
2
-
3
- class ModelTest < Minitest::Spec
4
- Song = Struct.new(:id) do
5
- def self.find(id); new(id) end
6
- def self.find_by(id:nil); id.nil? ? nil : new(id) end
7
- end
8
-
9
- #---
10
- # use Model semantics, no customizations.
11
- class Create < Trailblazer::Operation
12
- step Model Song, :new
13
- end
14
-
15
- # :new new.
16
- it { Create.({})["model"].inspect.must_equal %{#<struct ModelTest::Song id=nil>} }
17
-
18
- class Update < Create
19
- step Model( Song, :find ), override: true
20
- end
21
-
22
- # :find it
23
- it { Update.({ id: 1 })["model"].inspect.must_equal %{#<struct ModelTest::Song id=1>} }
24
-
25
- #- inheritance
26
- it { Update["pipetree"].inspect.must_equal %{[>operation.new,>model.build]} }
27
-
28
- #---
29
- # :find_by, exceptionless.
30
- class Find < Trailblazer::Operation
31
- step Model Song, :find_by
32
- step :process
33
-
34
- def process(*); self["x"] = true end
35
- end
36
-
37
- # can't find model.
38
- #- result object, model
39
- it do
40
- Find.(id: nil)["result.model"].failure?.must_equal true
41
- Find.(id: nil)["x"].must_equal nil
42
- Find.(id: nil).failure?.must_equal true
43
- end
44
-
45
- #- result object, model
46
- it do
47
- Find.(id: 9)["result.model"].success?.must_equal true
48
- Find.(id: 9)["x"].must_equal true
49
- Find.(id: 9)["model"].inspect.must_equal %{#<struct ModelTest::Song id=9>}
50
- end
51
-
52
- # #---
53
- # # creating the model before operation instantiation (ex Model::External)
54
- # class Show < Create
55
- # extend Model::BuildMethods # FIXME: how do we communicate that and prevent the include from Model[] ?
56
- # step Model( Song, :update ), before: "operation.new"
57
- # end
58
-
59
- # it { Show.({id: 1})["model"].inspect.must_equal %{#<struct ModelTest::Song id=1>} }
60
- end
@@ -1,36 +0,0 @@
1
- require "test_helper"
2
- require "trailblazer/operation/params"
3
-
4
- class OperationParamsTest < MiniTest::Spec
5
- #---
6
- # in call(params) and process(params), argument is always self["params"]
7
- class Find < Trailblazer::Operation
8
- def process(params); self["eql?"] = self["params"].object_id==params.object_id end
9
- end
10
- class Seek < Trailblazer::Operation
11
- include Test::ReturnCall
12
- def call(params); self["eql?"] = self["params"].object_id==params.object_id end
13
- end
14
-
15
-
16
- it { Find.({ id: 1 })["eql?"].must_equal true }
17
- # self["params"] is what gets passed in.
18
- it { Find.({ id: 1 })["params"].must_equal({ id: 1 }) }
19
- it { Seek.({ id: 1 }).must_equal true }
20
-
21
-
22
- #---
23
- # change self["params"] via Operation#
24
- class Create < Trailblazer::Operation
25
- include Params
26
- def process(params) self[:x] = params end
27
- def params!(params); params.merge(garrett: "Rocks!") end
28
- end
29
-
30
- # allows you changing params in #setup_params!.
31
- it {
32
- result = Create.( id: 1 )
33
- result["params"].inspect.must_equal %{{:id=>1, :garrett=>\"Rocks!\"}}
34
- result["params.original"].inspect.must_equal %{{:id=>1}}
35
- }
36
- end
@@ -1,44 +0,0 @@
1
- require "test_helper"
2
-
3
- class PersistTest < Minitest::Spec
4
- Song = Struct.new(:title, :saved) do
5
- def save; title=="Fail!" ? false : self.saved = true; end
6
- end
7
-
8
- class Create < Trailblazer::Operation
9
- extend Contract::DSL
10
- contract do
11
- property :title
12
- end
13
-
14
- step Model( Song, :new )
15
- step Contract::Build()
16
- step Contract::Validate()
17
- failure ->(options) { options["1. fail"] = "Validate" }
18
- step Contract::Persist()
19
- failure ->(options) { options["2. fail"] = "Persist" }
20
- end
21
-
22
- it { Create.(title: "In Recital")["model"].title.must_equal "In Recital" }
23
- it { Create.(title: "In Recital")["model"].saved.must_equal true }
24
- # failure
25
- it do
26
- result = Create.(title: "Fail!")
27
- result["model"].saved.must_equal nil
28
- result["model"].title.must_equal "Fail!"
29
- result["2. fail"].must_equal "Persist"
30
- result.success?.must_equal false
31
- end
32
-
33
- #---
34
- #- inheritance
35
- class Update < Create
36
- end
37
-
38
- it { Update["pipetree"].inspect.must_equal %{[>operation.new,>model.build,>contract.build,>contract.default.validate,<persist_test.rb:17,>persist.save,<persist_test.rb:19]} }
39
-
40
- #---
41
- it do
42
- skip "show how save! could be applied and how we could rescue and deviate to left track"
43
- end
44
- end
@@ -1,59 +0,0 @@
1
- require "test_helper"
2
-
3
- class PipedreamTest < Minitest::Spec
4
- Song = Struct.new(:title)
5
-
6
- class Create < Trailblazer::Operation
7
- class MyContract < Reform::Form
8
- property :title
9
- end
10
-
11
- class Auth
12
- def initialize(user, model); @user, @model = user, model end
13
- def user_and_model?; @user == Module && @model.class == Song end
14
- end
15
-
16
- # design principles:
17
- # * include as less code as possible into the op class.
18
- # * make the flow super explicit without making it cryptic (only 3 new operators)
19
- # * avoid including DSL modules in favor of passing those configurations directly to the "step".
20
-
21
-
22
-
23
- step Model[ Song, :new ] # model!)
24
- step Policy::Guard[ ->(options){ options["current_user"] == ::Module } ]
25
- step Contract[ MyContract]
26
- step Policy[ Auth, :user_and_model?]
27
- failure Contract[ MyContract]
28
-
29
- # step :model
30
- # step :guard
31
- # step :contract
32
-
33
-
34
- # ok Model[Song, :new] # model!)
35
- # ok Policy::Guard[ ->(options){ options["current_user"] == ::Module } ]
36
- # ok Contract[MyContract]
37
- # fail Contract[MyContract]
38
- # step> "contract"
39
-
40
- # | :bla
41
- # | ->
42
-
43
- end
44
-
45
- # TODO: test with contract constant (done).
46
- # test with inline contract.
47
- # test with override contract!.
48
-
49
- it do
50
- puts Create["pipetree"].inspect(style: :rows)
51
- result = Create.({}, { "current_user" => Module })
52
-
53
- result["model"].inspect.must_equal %{#<struct PipedreamTest::Song title=nil>}
54
- result["result.policy"].success?.must_equal true
55
- result["contract"].class.superclass.must_equal Reform::Form
56
-
57
-
58
- end
59
- end
@@ -1,104 +0,0 @@
1
- require "test_helper"
2
-
3
- # self["pipetree"] = ::Pipetree[
4
- # Trailblazer::Operation::New,
5
- # # SetupParams,
6
- # Trailblazer::Operation::Model::Build,
7
- # Trailblazer::Operation::Model::Assign,
8
- # Trailblazer::Operation::Call,
9
- # ]
10
-
11
-
12
-
13
- # def deserialize(*)
14
- # super
15
- # self.datetime = DateTime.parse("#{date} #{time}")
16
- # end
17
-
18
- class PipetreeTest < Minitest::Spec
19
- Song = Struct.new(:title)
20
-
21
- class Create < Trailblazer::Operation
22
- include Builder
23
- include Pipetree # this will add the functions, again, unfortunately. definitely an error source.
24
- end
25
-
26
- it { Create["pipetree"].inspect.must_equal %{[>>Build,>>New,>>Call,Result::Build,>>New,>>Call,Result::Build]} }
27
-
28
- #---
29
- # playground
30
- require "trailblazer/operation/policy"
31
- require "trailblazer/operation/guard"
32
-
33
- class Edit < Trailblazer::Operation
34
- include Builder
35
- include Policy::Guard
36
- include Contract::Step
37
- contract do
38
- property :title
39
- validates :title, presence: true
40
- end
41
-
42
-
43
- MyValidate = ->(input, options) { res= input.validate(options["params"]) { |f| f.sync } }
44
- # we can have a separate persist step and wrap in transaction. where do we pass contract, though?
45
- step MyValidate, before: Call #replace: Contract::ValidLegacySwitch
46
- #
47
- MyAfterSave = ->(input, options) { input["after_save"] = true }
48
- success MyAfterSave, after: MyValidate
49
-
50
- ValidateFailureLogger = ->(input, options) { input["validate fail"] = true }
51
- failure ValidateFailureLogger, after: MyValidate
52
-
53
- success ->(input, options) { input.process(options["params"]) }, replace: Call, name: "my.params"
54
-
55
- include Model
56
-
57
- LogBreach = ->(input, options) { input.log_breach! }
58
-
59
- failure LogBreach, after: Policy::Evaluate
60
-
61
- model Song
62
- policy ->(*) { self["current_user"] }
63
-
64
- def log_breach!
65
- self["breach"] = true
66
- end
67
-
68
- def process(params)
69
- self["my.valid"] = true
70
- end
71
-
72
- self["pipetree"]._insert(Contract::ValidLegacySwitch, {delete: true}, nil, nil)
73
- end
74
-
75
- puts Edit["pipetree"].inspect(style: :rows)
76
-
77
- it { Edit["pipetree"].inspect.must_equal %{[>>operation.build,>>operation.new,&model.build,&policy.guard.evaluate,<LogBreach,>contract.build,&MyValidate,<ValidateFailureLogger,>MyAfterSave,>my.params["params"]]} }
78
-
79
- # valid case.
80
- it {
81
- # puts "valid"
82
- # puts Edit["pipetree"].inspect(style: :rows)
83
- result = Edit.({ title: "Stupid 7" }, "current_user" => true)
84
- # puts "success! #{result.inspect}"
85
- result["my.valid"].must_equal true
86
- result["breach"].must_equal nil
87
- result["after_save"].must_equal true
88
- result["validate fail"].must_equal nil
89
- }
90
- # beach! i mean breach!
91
- it {
92
- # puts "beach"
93
- # puts Edit["pipetree"].inspect(style: :rows)
94
- result = Edit.({})
95
- # puts "@@@@@ #{result.inspect}"
96
- result["my.valid"].must_equal nil
97
- result["breach"].must_equal true
98
- result["validate fail"].must_equal true
99
- result["after_save"].must_equal nil
100
- }
101
- end
102
-
103
- # TODO: show the execution path in pipetree
104
- # unified result.contract, result.policy interface
@@ -1,24 +0,0 @@
1
- require "test_helper"
2
-
3
- require "trailblazer/operation/present"
4
-
5
- class PresentTest < Minitest::Spec
6
- class Create < Trailblazer::Operation
7
- include Test::ReturnCall
8
- include Present
9
-
10
- include Model::Builder
11
- def model!(*); Object end
12
-
13
- def call(params)
14
- "#call run!"
15
- end
16
- end
17
-
18
- it do
19
- result = Create.present
20
- result["model"].must_equal Object
21
- end
22
-
23
- it { Create.().must_equal "#call run!" }
24
- end
@@ -1,104 +0,0 @@
1
- require "test_helper"
2
- require "trailblazer/operation/policy"
3
-
4
- class PolicyTest < Minitest::Spec
5
- Song = Struct.new(:id) do
6
- def self.find(id); new(id) end
7
- end
8
-
9
- class Auth
10
- def initialize(user, model); @user, @model = user, model end
11
- def only_user?; @user == Module && @model.nil? end
12
- def user_object?; @user == Object end
13
- def user_and_model?; @user == Module && @model.class == Song end
14
- def inspect; "<Auth: user:#{@user.inspect}, model:#{@model.inspect}>" end
15
- end
16
-
17
- #---
18
- # Instance-level: Only policy, no model
19
- class Create < Trailblazer::Operation
20
- step Policy::Pundit( Auth, :only_user? )
21
- step :process
22
-
23
- def process(*)
24
- self["process"] = true
25
- end
26
- end
27
-
28
- # successful.
29
- it do
30
- result = Create.({}, "current_user" => Module)
31
- result["process"].must_equal true
32
- #- result object, policy
33
- result["result.policy.default"].success?.must_equal true
34
- result["result.policy.default"]["message"].must_equal nil
35
- # result[:valid].must_equal nil
36
- result["policy.default"].inspect.must_equal %{<Auth: user:Module, model:nil>}
37
- end
38
- # breach.
39
- it do
40
- result = Create.({}, "current_user" => nil)
41
- result["process"].must_equal nil
42
- #- result object, policy
43
- result["result.policy.default"].success?.must_equal false
44
- result["result.policy.default"]["message"].must_equal "Breach"
45
- end
46
- # inject different policy.Condition it { Create.({}, "current_user" => Object, "policy.default.eval" => Trailblazer::Operation::Policy::Pundit::Condition.new(Auth, :user_object?))["process"].must_equal true }
47
- it { Create.({}, "current_user" => Module, "policy.default.eval" => Trailblazer::Operation::Policy::Pundit::Condition.new(Auth, :user_object?))["process"].must_equal nil }
48
-
49
-
50
- #---
51
- # inheritance, adding Model
52
- class Show < Create
53
- step Model( Song, :new ), before: "policy.default.eval"
54
- end
55
-
56
- it { Show["pipetree"].inspect.must_equal %{[>operation.new,>model.build,>policy.default.eval,>process]} }
57
-
58
- # invalid because user AND model.
59
- it do
60
- result = Show.({}, "current_user" => Module)
61
- result["process"].must_equal nil
62
- result["model"].inspect.must_equal %{#<struct PolicyTest::Song id=nil>}
63
- # result["policy"].inspect.must_equal %{#<struct PolicyTest::Song id=nil>}
64
- end
65
-
66
- # valid because new policy.
67
- it do
68
- # puts Show["pipetree"].inspect
69
- result = Show.({}, "current_user" => Module, "policy.default.eval" => Trailblazer::Operation::Policy::Pundit::Condition.new(Auth, :user_and_model?))
70
- result["process"].must_equal true
71
- result["model"].inspect.must_equal %{#<struct PolicyTest::Song id=nil>}
72
- result["policy.default"].inspect.must_equal %{<Auth: user:Module, model:#<struct PolicyTest::Song id=nil>>}
73
- end
74
-
75
- ##--
76
- # TOOOODOOO: Policy and Model before Build ("External" or almost Resolver)
77
- class Edit < Trailblazer::Operation
78
- step Model Song, :find
79
- step Policy::Pundit( Auth, :user_and_model? )
80
- step :process
81
-
82
- def process(*); self["process"] = true end
83
- end
84
-
85
- # successful.
86
- it do
87
- result = Edit.({ id: 1 }, "current_user" => Module)
88
- result["process"].must_equal true
89
- result["model"].inspect.must_equal %{#<struct PolicyTest::Song id=1>}
90
- result["result.policy.default"].success?.must_equal true
91
- result["result.policy.default"]["message"].must_equal nil
92
- # result[:valid].must_equal nil
93
- result["policy.default"].inspect.must_equal %{<Auth: user:Module, model:#<struct PolicyTest::Song id=1>>}
94
- end
95
-
96
- # breach.
97
- it do
98
- result = Edit.({ id: 4 }, "current_user" => nil)
99
- result["model"].inspect.must_equal %{#<struct PolicyTest::Song id=4>}
100
- result["process"].must_equal nil
101
- result["result.policy.default"].success?.must_equal false
102
- result["result.policy.default"]["message"].must_equal "Breach"
103
- end
104
- end
@@ -1,254 +0,0 @@
1
- require "test_helper"
2
- require "representable/json"
3
-
4
- class RepresenterTest < MiniTest::Spec
5
- Album = Struct.new(:title, :artist)
6
- Artist = Struct.new(:name)
7
-
8
- class Create < Trailblazer::Operation
9
- include Contract::Explicit
10
- include Representer
11
- include Representer::InferFromContract
12
- attr_reader :model # FIXME: all we want is #model.
13
-
14
- contract do
15
- property :title
16
- validates :title, presence: true
17
- property :artist, populate_if_empty: Artist do
18
- property :name
19
- validates :name, presence: true
20
- end
21
- end
22
-
23
- def call(params)
24
- self["model"] = Album.new # NO artist!!!
25
- validate(params[:album], model: self["model"])
26
- self
27
- end
28
- end
29
-
30
-
31
- # Infers representer from contract, no customization.
32
- class Show < Create
33
- def call(params)
34
- self["model"] = Album.new("After The War", Artist.new("Gary Moore"))
35
- self
36
- end
37
- end
38
-
39
-
40
- # Infers representer, adds hypermedia.
41
- require "roar/json/hal"
42
- class HypermediaCreate < Create
43
- representer do
44
- include Roar::JSON::HAL
45
-
46
- link(:self) { "//album/#{represented.title}" }
47
- end
48
- end
49
-
50
- class HypermediaShow < HypermediaCreate
51
- def call(params)
52
- self["model"] = Album.new("After The War", Artist.new("Gary Moore"))
53
- self
54
- end
55
- end
56
-
57
-
58
- # rendering
59
- # generic contract -> representer
60
- it { Show.().to_json.must_equal %{{"title":"After The War","artist":{"name":"Gary Moore"}}} }
61
-
62
- # contract -> representer with hypermedia
63
- it do
64
- HypermediaShow.().to_json.must_equal %{{"title":"After The War","artist":{"name":"Gary Moore"},"_links":{"self":{"href":"//album/After The War"}}}}
65
- end
66
-
67
-
68
- # parsing
69
- it do
70
- op = Create.(album: %{{"title":"Run For Cover","artist":{"name":"Gary Moore"}}})
71
- op.contract.title.must_equal "Run For Cover"
72
- op.contract.artist.name.must_equal "Gary Moore"
73
- end
74
-
75
- it do
76
- op = HypermediaCreate.(album: %{{"title":"After The War","artist":{"name":"Gary Moore"},"_links":{"self":{"href":"//album/After The War"}}}})
77
- op.contract.title.must_equal "After The War"
78
- op.contract.artist.name.must_equal "Gary Moore"
79
- end
80
-
81
-
82
-
83
-
84
-
85
- # explicit representer set with ::representer_class=.
86
- require "roar/decorator"
87
- class JsonApiCreate < Trailblazer::Operation
88
- include Contract::Explicit
89
- include Representer
90
- attr_reader :model
91
-
92
- contract do # we still need contract as the representer writes to the contract twin.
93
- property :title
94
- end
95
-
96
- class AlbumRepresenter < Roar::Decorator
97
- include Roar::JSON
98
- property :title
99
- end
100
-
101
- # FIXME: this won't inherit, of course.
102
- # self["representer.class"] = AlbumRepresenter
103
- representer AlbumRepresenter
104
-
105
- def call(params)
106
- self["model"] = Album.new # NO artist!!!
107
- validate(params[:album], model: self["model"])
108
- self
109
- end
110
- end
111
-
112
- class JsonApiShow < JsonApiCreate
113
- def call(params)
114
- self["model"] = Album.new("After The War", Artist.new("Gary Moore"))
115
- self
116
- end
117
- end
118
-
119
- # render.
120
- it do
121
- JsonApiShow.().to_json.must_equal %{{"title":"After The War"}}
122
- end
123
-
124
- # parse.
125
- it do
126
- JsonApiCreate.(album: %{{"title":"Run For Cover"}}).contract.title.must_equal "Run For Cover"
127
- end
128
- end
129
-
130
- class InternalRepresenterAPITest < MiniTest::Spec
131
- Song = Struct.new(:id)
132
-
133
- describe "#represented" do
134
- class Show < Trailblazer::Operation
135
- include Contract::Explicit
136
- include Representer, Model
137
- model Song, :create
138
-
139
- representer do
140
- property :class
141
- end
142
-
143
- def call(*)
144
- self
145
- end
146
-
147
- def model # FIXME.
148
- self["model"]
149
- end
150
- end
151
-
152
- it "uses #model as represented, per default" do
153
- Show.({}).to_json.must_equal '{"class":"InternalRepresenterAPITest::Song"}'
154
- end
155
-
156
- class ShowContract < Show
157
- def represented
158
- "Object"
159
- end
160
- end
161
-
162
- it "can be overriden to use the contract" do
163
- ShowContract.({}).to_json.must_equal %{{"class":"String"}}
164
- end
165
- end
166
-
167
- describe "#to_json" do
168
- class OptionsShow < Trailblazer::Operation
169
- include Representer
170
-
171
- representer do
172
- property :class
173
- property :id
174
- end
175
-
176
- def to_json(*)
177
- super(self["params"])
178
- end
179
-
180
- include Model::Builder
181
- def model!(*)
182
- Song.new(1)
183
- end
184
- end
185
-
186
- it "allows to pass options to #to_json" do
187
- OptionsShow.(include: [:id]).to_json.must_equal %{{"id":1}}
188
- end
189
- end
190
- end
191
-
192
- class DifferentParseAndRenderingRepresenterTest < MiniTest::Spec
193
- Album = Struct.new(:title)
194
-
195
- # rendering
196
- class Create < Trailblazer::Operation
197
- include Contract::Explicit
198
- extend Representer::DSL
199
- include Representer::Rendering # no Deserializer::Hash here or anything.
200
-
201
- contract do
202
- property :title
203
- end
204
-
205
- representer do
206
- property :title, as: :Title
207
- end
208
-
209
- def call(params)
210
- self["model"] = Album.new
211
- validate(params) do
212
- contract.sync
213
- end
214
- self
215
- end
216
- end
217
-
218
- it do
219
- Create.(title: "The Kids").to_json.must_equal %{{"Title":"The Kids"}}
220
- end
221
-
222
- # parsing
223
- class Update < Trailblazer::Operation
224
- include Contract::Explicit
225
- extend Representer::DSL
226
- include Representer::Deserializer::Hash # no Rendering.
227
-
228
- representer do
229
- property :title, as: :Title
230
- end
231
-
232
- contract do
233
- property :title
234
- end
235
-
236
- def call(params)
237
- self["model"] = Album.new
238
-
239
- validate(params) do
240
- contract.sync
241
- end
242
-
243
- self
244
- end
245
-
246
- def to_json(*)
247
- %{{"title": "#{self["model"].title}"}}
248
- end
249
- end
250
-
251
- it do
252
- Update.("Title" => "The Kids").to_json.must_equal %{{"title": "The Kids"}}
253
- end
254
- end