trailblazer 2.0.7 → 2.1.0

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