yaks 0.7.7 → 0.8.0.alpha

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -0
  3. data/Rakefile +1 -1
  4. data/lib/yaks/attributes.rb +17 -11
  5. data/lib/yaks/builder.rb +43 -0
  6. data/lib/yaks/changelog.rb +2 -2
  7. data/lib/yaks/collection_mapper.rb +0 -2
  8. data/lib/yaks/config.rb +52 -32
  9. data/lib/yaks/configurable.rb +43 -14
  10. data/lib/yaks/errors.rb +1 -0
  11. data/lib/yaks/format/collection_json.rb +37 -5
  12. data/lib/yaks/format/hal.rb +8 -2
  13. data/lib/yaks/format/halo.rb +16 -9
  14. data/lib/yaks/format/json_api.rb +21 -2
  15. data/lib/yaks/format.rb +21 -15
  16. data/lib/yaks/html5_forms.rb +3 -2
  17. data/lib/yaks/identifier/link_relation.rb +17 -0
  18. data/lib/yaks/mapper/attribute.rb +2 -2
  19. data/lib/yaks/mapper/config.rb +1 -15
  20. data/lib/yaks/mapper/form/config.rb +21 -0
  21. data/lib/yaks/mapper/form/field/option.rb +20 -0
  22. data/lib/yaks/mapper/form/field.rb +13 -26
  23. data/lib/yaks/mapper/form/fieldset.rb +43 -0
  24. data/lib/yaks/mapper/form.rb +41 -16
  25. data/lib/yaks/mapper/link.rb +9 -7
  26. data/lib/yaks/mapper.rb +15 -7
  27. data/lib/yaks/null_resource.rb +2 -1
  28. data/lib/yaks/pipeline.rb +42 -0
  29. data/lib/yaks/primitivize.rb +0 -1
  30. data/lib/yaks/reader/hal.rb +63 -0
  31. data/lib/yaks/resource/form/field.rb +19 -0
  32. data/lib/yaks/resource/form/fieldset.rb +13 -0
  33. data/lib/yaks/resource/form.rb +6 -10
  34. data/lib/yaks/resource.rb +19 -2
  35. data/lib/yaks/runner.rb +13 -38
  36. data/lib/yaks/serializer.rb +34 -1
  37. data/lib/yaks/util.rb +8 -2
  38. data/lib/yaks/version.rb +1 -1
  39. data/lib/yaks.rb +37 -10
  40. data/resources/iana-link-relations.csv +152 -0
  41. data/spec/acceptance/acceptance_spec.rb +4 -3
  42. data/spec/acceptance/json_shared_examples.rb +11 -0
  43. data/spec/acceptance/models.rb +1 -1
  44. data/spec/integration/dynamic_form_fields_spec.rb +36 -0
  45. data/spec/integration/fieldset_spec.rb +62 -0
  46. data/spec/integration/map_to_resource_spec.rb +0 -2
  47. data/spec/json/confucius.halo.json +0 -1
  48. data/spec/sanity_spec.rb +0 -2
  49. data/spec/spec_helper.rb +3 -3
  50. data/spec/unit/yaks/attributes_spec.rb +3 -5
  51. data/spec/unit/yaks/{stateful_builder_spec.rb → builder_spec.rb} +8 -10
  52. data/spec/unit/yaks/collection_mapper_spec.rb +0 -2
  53. data/spec/unit/yaks/collection_resource_spec.rb +0 -2
  54. data/spec/unit/yaks/config_spec.rb +9 -15
  55. data/spec/unit/yaks/default_policy/derive_mapper_from_object_spec.rb +0 -2
  56. data/spec/unit/yaks/default_policy_spec.rb +0 -2
  57. data/spec/unit/yaks/format/collection_json_spec.rb +195 -3
  58. data/spec/unit/yaks/format/hal_spec.rb +0 -2
  59. data/spec/unit/yaks/format/halo_spec.rb +0 -1
  60. data/spec/unit/yaks/format/html_spec.rb +0 -2
  61. data/spec/unit/yaks/format/json_api_spec.rb +0 -2
  62. data/spec/unit/yaks/format_spec.rb +4 -6
  63. data/spec/unit/yaks/fp/callable_spec.rb +0 -2
  64. data/spec/unit/yaks/fp_spec.rb +0 -2
  65. data/spec/unit/yaks/mapper/association_mapper_spec.rb +0 -2
  66. data/spec/unit/yaks/mapper/association_spec.rb +0 -2
  67. data/spec/unit/yaks/mapper/attribute_spec.rb +0 -2
  68. data/spec/unit/yaks/mapper/config_spec.rb +6 -167
  69. data/spec/unit/yaks/mapper/form/field_spec.rb +0 -2
  70. data/spec/unit/yaks/mapper/form_spec.rb +2 -26
  71. data/spec/unit/yaks/mapper/has_many_spec.rb +0 -2
  72. data/spec/unit/yaks/mapper/has_one_spec.rb +0 -2
  73. data/spec/unit/yaks/mapper/link_spec.rb +13 -2
  74. data/spec/unit/yaks/mapper_spec.rb +2 -10
  75. data/spec/unit/yaks/null_resource_spec.rb +2 -4
  76. data/spec/unit/yaks/pipeline_spec.rb +140 -0
  77. data/spec/unit/yaks/primitivize_spec.rb +0 -2
  78. data/spec/unit/yaks/resource/link_spec.rb +0 -2
  79. data/spec/unit/yaks/resource_spec.rb +2 -4
  80. data/spec/unit/yaks/runner_spec.rb +52 -92
  81. data/spec/unit/yaks/serializer_spec.rb +0 -2
  82. data/spec/unit/yaks/util_spec.rb +12 -2
  83. metadata +58 -23
  84. data/lib/yaks/config/dsl.rb +0 -174
  85. data/lib/yaks/mapper/class_methods.rb +0 -47
  86. data/lib/yaks/stateful_builder.rb +0 -63
  87. data/spec/unit/yaks/config/dsl_spec.rb +0 -92
  88. data/spec/unit/yaks/configurable_spec.rb +0 -55
  89. data/spec/unit/yaks/mapper/class_methods_spec.rb +0 -83
@@ -1,174 +0,0 @@
1
- module Yaks
2
- class Config
3
- class DSL
4
- # @!attribute [r] config
5
- # @return [Yaks::Config]
6
- attr_reader :config
7
-
8
- # @param [Yaks::Config] config
9
- # @param [Proc] block
10
- def initialize(config, &block)
11
- @config = config
12
- @policy_class = Class.new(DefaultPolicy)
13
- @policies = []
14
- instance_eval(&block) if block
15
- @policies.each do |policy_block|
16
- @policy_class.class_eval &policy_block
17
- end
18
- config.policy_class = @policy_class
19
- end
20
-
21
- # Set the options for a format
22
- #
23
- # @param [Symbol] format
24
- # @param [Hash] options
25
- #
26
- # @example
27
- #
28
- # yaks = Yaks.new do
29
- # format_options :hal, {plural_links: [:related_content]}
30
- # end
31
- #
32
- def format_options(format, options)
33
- config.format_options[format] = options
34
- end
35
-
36
- # Set the default format
37
- #
38
- # Defaults to +:hal+
39
- #
40
- # @param [Symbol] format
41
- # Format identifier, one of +Yaks::Format.names+
42
- #
43
- # @example
44
- #
45
- # yaks = Yaks.new do
46
- # default_fomat :json_api
47
- # end
48
- #
49
- def default_format(format)
50
- config.default_format = format
51
- end
52
-
53
- # Configure serializer for specific output format, e.g. JSON
54
- #
55
- # This will override the default registered serializer. Note
56
- # that extension gems can register their own serializers, see
57
- # Yaks::Serializer.register
58
- #
59
- # @example
60
- #
61
- # yaks = Yaks.new do
62
- # serializer :json, &Oj.method(:dump)
63
- # end
64
- #
65
- # @type [Symbol] type
66
- # Output format
67
- # @param [Proc] serializer
68
- # Serialization procedure
69
- #
70
- def serializer(type, &serializer)
71
- config.serializers[type] = serializer
72
- end
73
-
74
- # @deprecated
75
- def json_serializer(&serializer)
76
- serializer(:json, &serializer)
77
- end
78
-
79
- %w[before after around skip].map(&:intern).each do |hook_type|
80
- define_method hook_type do |step, name = :"#{hook_type}_#{step}", &block|
81
- config.hooks << [hook_type, step, name, block]
82
- end
83
- end
84
-
85
- # Set a different policy implementation
86
- #
87
- # By default Yaks uses +Yaks::DefaultPolicy+ to derive missing
88
- # information. You can swap in a class with a compatible
89
- # interface to change the default behavior
90
- #
91
- # To override a single policy method, simply call a method with
92
- # the same name as part of your Yaks configuration, passing a
93
- # block to define the new behavior.
94
- #
95
- # @example
96
- #
97
- # yaks = Yaks.new do
98
- # derive_type_from_mapper_class do |mapper_class|
99
- # mapper_class.name.sub(/Mapper^/,'')
100
- # end
101
- # end
102
- #
103
- # @param [Class] klass
104
- # Policy class
105
- #
106
- def policy(klass)
107
- @policy_class = klass
108
- end
109
-
110
- # Set the template for deriving rels
111
- #
112
- # Used to derive rels for links and subresources.
113
- #
114
- # @example
115
- #
116
- # yaks = Yaks.new do
117
- # rel_template 'http://api.example.com/rels/{rel}'
118
- # end
119
- #
120
- # @param [String] template
121
- # A valid URI template containing +{rel}+
122
- #
123
- def rel_template(template)
124
- config.policy_options[:rel_template] = template
125
- end
126
-
127
- # Set the namespace (Ruby module) that contains your mappers
128
- #
129
- # When your mappers don't live at the top-level, then set this
130
- # so Yaks can correctly infer the mapper class from the model
131
- # class.
132
- #
133
- # @example
134
- #
135
- # yaks = Yaks.new do
136
- # mapper_namespace API::Mappers
137
- # end
138
- #
139
- # module API::Mappers
140
- # class FruitMapper < Yaks::Mapper
141
- # ...
142
- # end
143
- # end
144
- #
145
- # class Fruit < BaseModel
146
- # ...
147
- # end
148
- #
149
- # @param [Module] namespace
150
- #
151
- def mapper_namespace(namespace)
152
- config.policy_options[:namespace] = namespace
153
- end
154
- alias namespace mapper_namespace
155
-
156
- # @param [Array] args
157
- # @param [Proc] block
158
- def map_to_primitive(*args, &block)
159
- config.primitivize.map(*args, &block)
160
- end
161
-
162
- # Will define each method available in the DefaultPolicy upon the DSL
163
- # and then make it available to apply to any Class taking on the
164
- # `@policies` Array.
165
- DefaultPolicy.public_instance_methods(false).each do |method|
166
- define_method method do |&block|
167
- @policies << proc {
168
- define_method method, &block
169
- }
170
- end
171
- end
172
- end
173
- end
174
- end
@@ -1,47 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- module Yaks
4
- class Mapper
5
- module ClassMethods
6
- extend Util::Deprecated
7
- include Forwardable,
8
- Util,
9
- FP
10
-
11
- def config(value = Undefined)
12
- if value.equal? Undefined
13
- @config
14
- else
15
- raise if value.nil?
16
- @config = value
17
- end
18
- end
19
-
20
- def inherited(child)
21
- child.config(config)
22
- end
23
-
24
- CONFIG_METHODS = [
25
- :type,
26
- :attributes,
27
- :link,
28
- :profile,
29
- :has_one,
30
- :has_many,
31
- :form
32
- ]
33
-
34
- CONFIG_METHODS.each do |method_name|
35
- define_method method_name do |*args, &block|
36
- if args.empty?
37
- config.public_send(method_name, *args, &block)
38
- else
39
- config(config.public_send(method_name, *args, &block))
40
- end
41
- end
42
- end
43
-
44
- deprecated_alias :control, :form
45
- end
46
- end
47
- end
@@ -1,63 +0,0 @@
1
- module Yaks
2
- # State monad-ish thing.
3
- #
4
- # Generate a DSL syntax for immutable classes.
5
- #
6
- # @example
7
- #
8
- # # This code
9
- # Form.create(:search)
10
- # .method("POST")
11
- # .action("/search")
12
- #
13
- # # Can be written as
14
- # StatefulBuilder.new(Form, [:method, :action]).create(:search) do
15
- # method "POST"
16
- # action "/search"
17
- # end
18
- #
19
- class StatefulBuilder < BasicObject
20
- def create(*args, &block)
21
- build(@klass.create(*args), &block)
22
- end
23
-
24
- def build(init_state, &block)
25
- @state = init_state
26
- instance_eval(&block) if block
27
- @state
28
- end
29
-
30
- def initialize(klass, methods = nil)
31
- @klass = klass
32
- @methods = methods || klass.attributes.names
33
- StatefulMethods.new(@methods).send(:extend_object, self)
34
- end
35
-
36
- def validate_state(method_name, args)
37
- unless @state.instance_of?(@klass)
38
- ::Kernel.raise(
39
- IllegalStateError,
40
- "#{@klass}##{method_name}(#{args.map(&:inspect).join(', ')}) "\
41
- "returned #{@state.inspect}. Expected instance of #{@klass}"
42
- )
43
- end
44
- end
45
-
46
- def inspect
47
- "#<StatefulBuilder #{@klass} #{@methods.inspect}>"
48
- end
49
-
50
- class StatefulMethods < ::Module
51
- def initialize(methods)
52
- methods.each { |name| define_stateful_method(name) }
53
- end
54
-
55
- def define_stateful_method(method_name)
56
- define_method method_name do |*args, &block|
57
- @state = @state.public_send(method_name, *args, &block)
58
- validate_state(method_name, args)
59
- end
60
- end
61
- end
62
- end
63
- end
@@ -1,92 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe Yaks::Config::DSL do
4
- subject!(:dsl) { described_class.new(yaks_config, &config_block) }
5
-
6
- let(:yaks_config) { Yaks::Config.new }
7
- let(:config_block) { nil }
8
-
9
- def self.configure(&blk)
10
- let(:config_block) { blk }
11
- end
12
-
13
- describe '#initialize' do
14
- its(:config) { should equal yaks_config }
15
-
16
- it 'should set a default policy' do
17
- expect(yaks_config.policy_class.new).to be_a_kind_of Yaks::DefaultPolicy
18
- end
19
-
20
- it 'should execute the given block in instance scope' do
21
- dsl = described_class.new(yaks_config) do
22
- @config = :foo
23
- end
24
- expect(dsl.config).to be :foo
25
- end
26
-
27
- describe 'policy redefinitions' do
28
- configure do
29
- derive_type_from_mapper_class do |mapper_class|
30
- :inside_redefined_policy_method
31
- end
32
- end
33
-
34
- it 'should delegate and redefine' do
35
- expect(yaks_config.policy.derive_type_from_mapper_class(nil)).to be :inside_redefined_policy_method
36
- end
37
-
38
- it 'should not change the original class definition' do
39
- expect(Yaks::DefaultPolicy.new.derive_type_from_mapper_class(fake(name: 'FooMapper'))).to eql 'foo'
40
- end
41
- end
42
- end
43
-
44
- describe '#format_options' do
45
- configure { format_options :hal, singular_link: [:self] }
46
- specify { expect(yaks_config.format_options[:hal]).to eq(singular_link: [:self]) }
47
- end
48
-
49
- describe '#default_format' do
50
- configure { default_format :json_api }
51
- specify { expect(yaks_config.default_format).to be :json_api }
52
- end
53
-
54
- describe '#policy' do
55
- configure { policy 'MyPolicyClass' }
56
- specify { expect(yaks_config.policy_class).to eql 'MyPolicyClass' }
57
- end
58
-
59
- describe '#rel_template' do
60
- configure { rel_template 'rels:{rel}' }
61
- specify { expect(yaks_config.policy_options[:rel_template]).to eql 'rels:{rel}' }
62
- end
63
-
64
- describe '#serializer' do
65
- configure { serializer(:json) { |i| "foo #{i}" } }
66
- specify { expect(yaks_config.serializers[:json].call(7)).to eql 'foo 7' }
67
- end
68
-
69
- describe '#json_serializer' do
70
- configure { json_serializer { |i| "foo #{i}" } }
71
- specify { expect(yaks_config.serializers[:json].call(7)).to eql 'foo 7' }
72
- end
73
-
74
- describe '#mapper_namespace' do
75
- configure { mapper_namespace RSpec }
76
- specify { expect(yaks_config.policy_options[:namespace]).to eql RSpec }
77
- end
78
-
79
- describe '#map_to_primitive' do
80
- Foo = Class.new do
81
- attr_reader :foo
82
-
83
- def initialize(foo)
84
- @foo = foo
85
- end
86
- end
87
-
88
- configure { map_to_primitive(Foo) {|c| c.foo } }
89
- specify { expect(yaks_config.primitivize.call({:abc => Foo.new('hello')})).to eql 'abc' => 'hello' }
90
- end
91
-
92
- end
@@ -1,55 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe Yaks::Configurable do
4
- class Creatable
5
- def self.create(*args, &block)
6
- ["->", *args, block.call]
7
- end
8
- end
9
-
10
- subject do
11
- Class.new do
12
- extend Yaks::Configurable
13
- include Yaks::Attributes.new(foo: [])
14
-
15
- config_method :bar, append_to: :foo, create: Creatable
16
- config_method :baz, append_to: :foo, create: Creatable, defaults: {bar: 'baz'}
17
- end
18
- end
19
-
20
- it 'should generate the config method' do
21
- expect(
22
- subject.new.bar(1,2,3) { 4 }
23
- .bar(:baz) { :booz }
24
- .foo
25
- ).to eql [["->", 1, 2, 3, {}, 4], ["->", :baz, {}, :booz]]
26
- end
27
-
28
- it 'should allow setting defaults' do
29
- expect(
30
- subject.new.baz(1,2,3, foo: 'bar') { 4 }
31
- .foo
32
- ).to eql [["->", 1, 2, 3, {foo: 'bar', bar: 'baz'}, 4]]
33
- end
34
-
35
- it 'should allow overriding defaults' do
36
- expect(
37
- subject.new.baz(1,2,3, bar: 'qux') { 4 }
38
- .foo
39
- ).to eql [["->", 1, 2, 3, {bar: 'qux'}, 4]]
40
- end
41
-
42
- it 'should be able to take an already instantiated object of the right type' do
43
- instance = Creatable.new
44
- expect(
45
- subject.new.bar(instance).foo
46
- ).to eql [instance]
47
- end
48
-
49
- it 'should only take the instance verbatim if it is the only argument' do
50
- instance = Creatable.new
51
- expect(
52
- subject.new.bar(instance, 1) {}.foo
53
- ).to eql [["->", instance, 1, {}, nil]]
54
- end
55
- end
@@ -1,83 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe Yaks::Mapper::ClassMethods do
4
- subject(:mapper_class) do
5
- Class.new do
6
- extend Yaks::Mapper::ClassMethods
7
- config Yaks::Mapper::Config.new
8
- attributes :foo, :bar
9
- link :some_rel, 'http://some_link'
10
- has_one :thing
11
- has_many :thingies
12
- end
13
- end
14
-
15
- describe 'attributes' do
16
- it 'should allow setting them' do
17
- expect( mapper_class.attributes ).to eq [
18
- Yaks::Mapper::Attribute.new(:foo),
19
- Yaks::Mapper::Attribute.new(:bar)
20
- ]
21
- end
22
-
23
- describe 'with inheritance' do
24
- let(:child_class) do
25
- Class.new(mapper_class) do
26
- attributes :baz
27
- end
28
- end
29
-
30
- let(:grandchild_class) do
31
- Class.new(child_class)
32
- end
33
-
34
- it 'should inherit attributes from the parent' do
35
- expect(child_class.attributes).to eq [
36
- Yaks::Mapper::Attribute.new(:foo),
37
- Yaks::Mapper::Attribute.new(:bar),
38
- Yaks::Mapper::Attribute.new(:baz)
39
- ]
40
- end
41
-
42
- it 'should create a valid config' do
43
- expect(grandchild_class.config).to be_a Yaks::Mapper::Config
44
- end
45
-
46
- it 'should not alter the parent' do
47
- expect(mapper_class.attributes).to eq [
48
- Yaks::Mapper::Attribute.new(:foo),
49
- Yaks::Mapper::Attribute.new(:bar),
50
- ]
51
- end
52
- end
53
- end
54
-
55
- it 'should register links' do
56
- expect(mapper_class.config.links).to eq [
57
- Yaks::Mapper::Link.new(rel: :some_rel, template: 'http://some_link')
58
- ]
59
- end
60
-
61
- it 'should register associations' do
62
- expect(mapper_class.config.associations).to eq [
63
- Yaks::Mapper::HasOne.new(name: :thing),
64
- Yaks::Mapper::HasMany.new(name: :thingies)
65
- ]
66
- end
67
-
68
- describe '#config' do
69
- it 'should allow getting the config' do
70
- expect(subject.config).to be_a Yaks::Mapper::Config
71
- end
72
-
73
- it 'should allow setting the config' do
74
- subject.config(:foo)
75
- expect(subject.config).to be :foo
76
- end
77
-
78
- it 'raise an exception when the config is nil' do
79
- expect { subject.config(nil) }.to raise_exception
80
- end
81
- end
82
-
83
- end