yaks 0.7.7 → 0.8.0.alpha

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 (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