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
@@ -0,0 +1,20 @@
1
+ module Yaks
2
+ class Mapper
3
+ class Form
4
+ class Field
5
+ # <option>, as used in a <select>
6
+ class Option
7
+ include Attributes.new(:value, :label, selected: false)
8
+
9
+ def self.create(value, opts = {})
10
+ new(opts.merge(value: value))
11
+ end
12
+
13
+ def to_resource
14
+ to_h #placeholder
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -2,14 +2,17 @@ module Yaks
2
2
  class Mapper
3
3
  class Form
4
4
  class Field
5
- extend Configurable
6
5
  include Attributes.new(
7
6
  :name,
8
7
  label: nil,
9
- options: []
8
+ options: [].freeze
10
9
  ).add(HTML5Forms::FIELD_OPTIONS)
11
10
 
12
- Builder = StatefulBuilder.new(self, attributes.names)
11
+ Builder = Builder.new(self) do
12
+ def_set :name
13
+ def_set :label
14
+ def_add :option, create: Option, append_to: :options
15
+ end
13
16
 
14
17
  def self.create(*args)
15
18
  attrs = args.last.instance_of?(Hash) ? args.pop : {}
@@ -25,38 +28,22 @@ module Yaks
25
28
  Resource::Form::Field.new(
26
29
  resource_attributes.each_with_object({}) do |attr, attrs|
27
30
  attrs[attr] = mapper.expand_value(public_send(attr))
28
- end.merge(options: options.map(&:to_resource))
31
+ end.merge(options: resource_options)
29
32
  )
30
33
  end
31
34
 
35
+ def resource_options
36
+ # make sure all empty options arrays are the same instance,
37
+ # makes for prettier #pp
38
+ options.empty? ? options : options.map(&:to_resource)
39
+ end
40
+
32
41
  # All attributes that can be converted 1-to-1 to
33
42
  # Resource::Form::Field
34
43
  def resource_attributes
35
44
  self.class.attributes.names - [:options]
36
45
  end
37
-
38
- # <option>, as used in a <select>
39
- class Option
40
- include Attributes.new(:value, :label, selected: false)
41
-
42
- def self.create(value, opts = {})
43
- new(opts.merge(value: value))
44
- end
45
-
46
- def to_resource
47
- to_h #placeholder
48
- end
49
- end
50
-
51
- config_method :option, create: Option, append_to: :options
52
46
  end #Field
53
-
54
- config_method :field, create: Field::Builder, append_to: :fields
55
-
56
- HTML5Forms::INPUT_TYPES.each do |type|
57
- config_method type, create: Field::Builder, append_to: :fields, defaults: { type: type }
58
- end
59
-
60
47
  end # Form
61
48
  end # Mapper
62
49
  end # Yaks
@@ -0,0 +1,43 @@
1
+ module Yaks
2
+ class Mapper
3
+ class Form
4
+ class Fieldset
5
+ extend Forwardable
6
+ include Concord.new(:config)
7
+
8
+ def_delegators :config, :fields, :dynamic_blocks
9
+
10
+ ConfigBuilder = Builder.new(Config) do
11
+ def_add :field, create: Field::Builder, append_to: :fields
12
+ def_add :fieldset, create: Fieldset, append_to: :fields
13
+ HTML5Forms::INPUT_TYPES.each do |type|
14
+ def_add(type,
15
+ create: Field::Builder,
16
+ append_to: :fields,
17
+ defaults: { type: type }
18
+ )
19
+ end
20
+ def_forward :dynamic
21
+ end
22
+
23
+ def self.create(_opts={}, &block)
24
+ new(ConfigBuilder.build(Config.new, &block))
25
+ end
26
+
27
+ def to_resource(mapper)
28
+ config = dynamic_blocks.inject(self.config) do |config, block|
29
+ ConfigBuilder.build(config, mapper.object, &block)
30
+ end
31
+
32
+ resource_fields = resource_fields(config.fields, mapper)
33
+
34
+ Resource::Form::Fieldset.new(fields: resource_fields)
35
+ end
36
+
37
+ def resource_fields(fields, mapper)
38
+ fields.map { |field| field.to_resource(mapper) }
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,41 +1,66 @@
1
1
  module Yaks
2
2
  class Mapper
3
3
  class Form
4
- extend Util::Deprecated, Configurable
5
- include Attributes.new(
6
- name: nil, action: nil, title: nil, method: nil, media_type: nil, fields: []
7
- )
4
+ extend Configurable, Forwardable, Util
8
5
 
9
- deprecated_alias :href, :action
6
+ ConfigBuilder = Builder.new(Config) do
7
+ def_set :action, :title, :method, :media_type
8
+ def_add :field, create: Field::Builder, append_to: :fields
9
+ def_add :fieldset, create: Fieldset, append_to: :fields
10
+ HTML5Forms::INPUT_TYPES.each do |type|
11
+ def_add(type,
12
+ create: Field::Builder,
13
+ append_to: :fields,
14
+ defaults: { type: type }
15
+ )
16
+ end
17
+ def_forward :dynamic
18
+ end
10
19
 
11
- Builder = StatefulBuilder.new(
12
- self,
13
- self.attributes.names + HTML5Forms::INPUT_TYPES + [:field]
14
- )
20
+ def_delegators :config, :name, :action, :title, :method,
21
+ :media_type, :fields, :dynamic_blocks
15
22
 
16
- def self.create(name = nil, options = {}, &block)
17
- Builder.build(new({name: name}.merge(options)), &block)
23
+ def self.create(*args, &block)
24
+ args, options = extract_options(args)
25
+
26
+ if args.first.is_a? Symbol
27
+ options[:name] = args.first
28
+ end
29
+
30
+ new(ConfigBuilder.build(Config.new(options), &block))
18
31
  end
19
32
 
33
+ ############################################################
34
+ # instance
35
+
36
+ include Concord.new(:config)
37
+
20
38
  def add_to_resource(resource, mapper, _context)
21
39
  resource.add_form(to_resource(mapper))
22
40
  end
23
41
 
42
+ private
43
+
24
44
  def to_resource(mapper)
45
+ config = dynamic_blocks.inject(self.config) do |config, block|
46
+ ConfigBuilder.build(config, mapper.object, &block)
47
+ end
48
+
25
49
  attrs = {
26
- fields: resource_fields(mapper),
27
- action: mapper.expand_uri(action, true)
50
+ fields: resource_fields(config.fields, mapper),
51
+ action: mapper.expand_uri(config.action, true)
28
52
  }
53
+
29
54
  [:name, :title, :method, :media_type].each do |attr|
30
- attrs[attr] = mapper.expand_value(public_send(attr))
55
+ attrs[attr] = mapper.expand_value(config.public_send(attr))
31
56
  end
57
+
32
58
  Resource::Form.new(attrs)
33
59
  end
34
60
 
35
- def resource_fields(mapper)
61
+ def resource_fields(fields, mapper)
36
62
  fields.map { |field| field.to_resource(mapper) }
37
63
  end
38
-
39
64
  end
40
65
  end
41
66
  end
@@ -24,19 +24,21 @@ module Yaks
24
24
  # @option title [#to_proc] Block that returns the title. If it takes an argument,
25
25
  # it will receive the mapper instance as argument. Otherwise it is evaluated in the mapper context
26
26
  class Link
27
- extend Forwardable
28
- include Attributes.new(:rel, :template, options: {})
29
- include Util
27
+ extend Forwardable, Util
28
+ include Attributes.new(:rel, :template, options: {}), Util
30
29
 
31
- def self.create(rel, template, options = {})
32
- new(rel: rel, template: template, options: options)
30
+ def self.create(*args)
31
+ args, options = extract_options(args)
32
+ new(rel: args[0], template: args[1], options: options)
33
33
  end
34
34
 
35
35
  def add_to_resource(resource, mapper, _context)
36
36
  resource_link = map_to_resource_link(mapper)
37
37
  return resource unless resource_link
38
- if options[:replace]
39
- resource.links(resource.links.reject {|link| link.rel?(rel)} << resource_link)
38
+ if options[:remove]
39
+ resource.with(links: resource.links.reject {|link| link.rel?(rel)})
40
+ elsif options[:replace]
41
+ resource.with(links: resource.links.reject {|link| link.rel?(rel)} << resource_link)
40
42
  else
41
43
  resource.add_link(resource_link)
42
44
  end
data/lib/yaks/mapper.rb CHANGED
@@ -1,17 +1,25 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  module Yaks
4
2
  class Mapper
5
- extend ClassMethods, Forwardable
6
- include Util, FP, FP::Callable
3
+ extend Configurable
7
4
 
8
- def_delegators 'self.class', :config
9
- def_delegators :config, :attributes, :links, :associations, :forms
5
+ def_forward :type => :with_type
6
+ def_forward :attributes => :add_attributes
7
+ def_forward :append_to
10
8
 
11
- config Config.new
9
+ def_add :link, create: Link, append_to: :links
10
+ def_add :has_one, create: HasOne, append_to: :associations
11
+ def_add :has_many, create: HasMany, append_to: :associations
12
+ def_add :attribute, create: Attribute, append_to: :attributes
13
+ def_add :form, create: Form, append_to: :forms
14
+
15
+ extend Forwardable
16
+ include Util, FP, FP::Callable
12
17
 
13
18
  attr_reader :object, :context
14
19
 
20
+ def_delegators 'self.class', :config
21
+ def_delegators :config, :attributes, :links, :associations, :forms
22
+
15
23
  def initialize(context)
16
24
  @context = context
17
25
  end
@@ -18,6 +18,7 @@ module Yaks
18
18
  @collection
19
19
  end
20
20
 
21
+
21
22
  def null_resource?
22
23
  true
23
24
  end
@@ -31,7 +32,7 @@ module Yaks
31
32
  raise UnsupportedOperationError, "Operation #{__method__} not supported on #{self.class}"
32
33
  end
33
34
 
34
- def update_attributes(_new_attrs)
35
+ def merge_attributes(_new_attrs)
35
36
  raise UnsupportedOperationError, "Operation #{__method__} not supported on #{self.class}"
36
37
  end
37
38
 
@@ -0,0 +1,42 @@
1
+ module Yaks
2
+ class Pipeline
3
+ include Concord.new(:steps)
4
+
5
+ def call(input, env)
6
+ steps.inject(input) {|memo, (_, step)| step.call(memo, env) }
7
+ end
8
+
9
+ def insert_hooks(hooks)
10
+ new_steps = hooks.inject(steps) do |steps, (type, target_step, name, hook)|
11
+ steps.flat_map do |step_name, callable|
12
+ if step_name.equal? target_step
13
+ case type
14
+ when :before
15
+ [[name, hook], [step_name, callable]]
16
+ when :after
17
+ [[step_name, callable], [name, hook]]
18
+ when :around
19
+ [[name, ->(x, env) { hook.call(x, env, &callable) }]]
20
+ when :skip
21
+ []
22
+ end
23
+ end || [[step_name, callable]]
24
+ end
25
+ end
26
+
27
+ self.class.new(new_steps)
28
+ end
29
+
30
+ def transitive?
31
+ steps.all? {|name, step| step.respond_to?(:transitive?) && step.transitive?}
32
+ end
33
+
34
+ def inverse
35
+ unless transitive?
36
+ raise RuntimeError, "Unable to get inverse pipeline, not all pipeline steps are transitive."
37
+ end
38
+
39
+ self.class.new(steps.map {|name, step| [name, step.inverse]}.reverse)
40
+ end
41
+ end
42
+ end
@@ -1,6 +1,5 @@
1
1
  module Yaks
2
2
  class Primitivize
3
-
4
3
  attr_reader :mappings
5
4
 
6
5
  def initialize
@@ -0,0 +1,63 @@
1
+ module Yaks
2
+ module Reader
3
+ class Hal
4
+
5
+ def call(parsed_json, env = {})
6
+ attributes = parsed_json.dup
7
+ links = convert_links(attributes.delete('_links') || {})
8
+ embedded = convert_embedded(attributes.delete('_embedded') || {})
9
+
10
+
11
+ Resource.new(
12
+ type: attributes.delete('type') || type_from_links(links),
13
+ attributes: Util.symbolize_keys(attributes),
14
+ links: links,
15
+ subresources: embedded
16
+ )
17
+ end
18
+
19
+ def type_from_links(links)
20
+ profile = links.detect {|l| l.rel?(:profile)}
21
+ profile.uri[/\w+$/] if profile
22
+ end
23
+
24
+ def convert_links(links)
25
+ Set[*
26
+ links.flat_map do |rel, link|
27
+ array(link).map do |l|
28
+ options = Util.symbolize_keys(Util.slice_hash(l, 'title', 'templated'))
29
+ rel = rel.to_sym if Yaks::Identifier::LinkRelation.iana?(rel)
30
+ Resource::Link.new(rel: rel, uri: l['href'], options: options)
31
+ end
32
+ end
33
+ ]
34
+ end
35
+
36
+ def array(x)
37
+ x.instance_of?(Array) ? x : [x]
38
+ end
39
+
40
+
41
+ def convert_embedded(embedded)
42
+ embedded.flat_map do |rel, resource|
43
+ case resource
44
+ when nil
45
+ NullResource.new
46
+ when Array
47
+ if resource.empty?
48
+ NullResource.new(collection: true)
49
+ else
50
+ CollectionResource.new(
51
+ members: resource.map { |r|
52
+ call(r).with(type: Util.singularize(rel[/\w+$/])) }
53
+ )
54
+ end
55
+ else
56
+ call(resource)
57
+ end.with(rels: [rel])
58
+ end
59
+ end
60
+
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,19 @@
1
+ module Yaks
2
+ class Resource
3
+ class Form
4
+ class Field
5
+ include Yaks::Mapper::Form::Field.attributes.add(:error => nil)
6
+
7
+ def value(arg = Undefined)
8
+ return @value if arg.eql?(Undefined)
9
+ if type == :select
10
+ selected = options.find { |option| option.selected }
11
+ selected.value if selected
12
+ else
13
+ with(value: arg)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ module Yaks
2
+ class Resource
3
+ class Form
4
+ class Fieldset
5
+ include Attributes.new(:fields)
6
+
7
+ def type
8
+ :fieldset
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,7 +1,7 @@
1
1
  module Yaks
2
2
  class Resource
3
3
  class Form
4
- include Yaks::Mapper::Form.attributes
4
+ include Yaks::Mapper::Form::Config.attributes.remove(:dynamic_blocks)
5
5
 
6
6
  def [](name)
7
7
  fields.find {|field| field.name == name}.value
@@ -13,16 +13,12 @@ module Yaks
13
13
  end
14
14
  end
15
15
 
16
- class Field
17
- include Yaks::Mapper::Form::Field.attributes.add(:error => nil)
18
-
19
- def value(arg = Undefined)
20
- return @value if arg.eql?(Undefined)
21
- if type == :select
22
- selected = options.find { |option| option.selected }
23
- selected.value if selected
16
+ def fields_flat(fields = fields)
17
+ fields.each_with_object([]) do |field, acc|
18
+ if field.type == :fieldset
19
+ acc.concat(fields_flat field.fields)
24
20
  else
25
- update(value: arg)
21
+ acc << field
26
22
  end
27
23
  end
28
24
  end
data/lib/yaks/resource.rb CHANGED
@@ -8,6 +8,7 @@ module Yaks
8
8
  subresources: [],
9
9
  forms: []
10
10
  )
11
+ extend Util::Deprecated
11
12
 
12
13
  def initialize(attrs = {})
13
14
  raise attrs.inspect if attrs.key?(:subresources) && !attrs[:subresources].instance_of?(Array)
@@ -27,6 +28,16 @@ module Yaks
27
28
  end
28
29
 
29
30
  def self_link
31
+ # This reverse is there so that the last :self link specified
32
+ # "wins". The use case is having a self link defined in a base
33
+ # mapper class, but having it overridden in specific
34
+ # subclasses. In combination with formats that expect resources
35
+ # to have up to one self link, this is the preferred behavior.
36
+ # However since 0.7.5 links take a "replace: true" option to
37
+ # specifiy they should replace previous defintions with the same
38
+ # rel, wich should be used instead. The behavior that the last
39
+ # link "wins" will be deprecated, the result of multiple links
40
+ # with the same rel will be unspecified.
30
41
  links.reverse.find do |link|
31
42
  link.rel.equal? :self
32
43
  end
@@ -37,6 +48,10 @@ module Yaks
37
48
  end
38
49
  alias collection collection?
39
50
 
51
+ def with_collection(*)
52
+ self
53
+ end
54
+
40
55
  def null_resource?
41
56
  false
42
57
  end
@@ -47,10 +62,12 @@ module Yaks
47
62
  alias each members
48
63
  alias map members
49
64
  alias each_with_object members
65
+ alias with_members members
50
66
 
51
- def update_attributes(new_attrs)
52
- update(attributes: @attributes.merge(new_attrs))
67
+ def merge_attributes(new_attrs)
68
+ with(attributes: @attributes.merge(new_attrs))
53
69
  end
70
+ deprecated_alias :update_attributes, :merge_attributes
54
71
 
55
72
  def add_rel(rel)
56
73
  append_to(:rels, rel)
data/lib/yaks/runner.rb CHANGED
@@ -5,18 +5,20 @@ module Yaks
5
5
  include Adamantium::Flat
6
6
  extend Forwardable
7
7
 
8
- def_delegators :config, :policy, :default_format, :format_options, :primitivize, :serializers
8
+ def_delegators :config, :policy, :default_format, :format_options_hash,
9
+ :primitivize, :serializers
10
+ def_delegators :format_class, :media_type, :format_name
9
11
 
10
12
  def call
11
- process(steps, object)
13
+ Pipeline.new(steps).insert_hooks(hooks).call(object, env)
12
14
  end
13
15
 
14
- def map(object)
15
- process(insert_hooks([[:map, mapper]]), object)
16
+ def read
17
+ Pipeline.new([[:parse, serializer.inverse], [:format, formatter.inverse]]).insert_hooks(hooks).call(object, env)
16
18
  end
17
19
 
18
- def process(operations, input)
19
- operations.inject(input) {|memo, (_, step)| step.call(memo, env) }
20
+ def map
21
+ Pipeline.new([[:map, mapper]]).insert_hooks(hooks).call(object, env)
20
22
  end
21
23
 
22
24
  def context
@@ -41,20 +43,11 @@ module Yaks
41
43
  end
42
44
  memoize :format_class
43
45
 
44
- def media_type
45
- format_class.media_type
46
- end
47
-
48
- def format_name
49
- format_class.format_name
50
- end
51
-
52
46
  def steps
53
- insert_hooks(
54
- [[ :map, mapper ],
55
- [ :format, formatter ],
56
- [ :primitivize, primitivizer],
57
- [ :serialize, serializer ]])
47
+ [[ :map, mapper ],
48
+ [ :format, formatter ],
49
+ [ :primitivize, primitivizer],
50
+ [ :serialize, serializer ]]
58
51
  end
59
52
  memoize :steps
60
53
 
@@ -66,7 +59,7 @@ module Yaks
66
59
  memoize :mapper, freezer: :noop
67
60
 
68
61
  def formatter
69
- format_class.new(format_options[format_name])
62
+ format_class.new(format_options_hash[format_name])
70
63
  end
71
64
  memoize :formatter
72
65
 
@@ -90,23 +83,5 @@ module Yaks
90
83
  config.hooks + options.fetch(:hooks, [])
91
84
  end
92
85
 
93
- def insert_hooks(steps)
94
- hooks.inject(steps) do |steps, (type, target_step, name, hook)|
95
- steps.flat_map do |step_name, callable|
96
- if step_name.equal? target_step
97
- case type
98
- when :before
99
- [[name, hook], [step_name, callable]]
100
- when :after
101
- [[step_name, callable], [name, hook]]
102
- when :around
103
- [[step_name, ->(x, env) { hook.call(x, env, &callable) }]]
104
- when :skip
105
- []
106
- end
107
- end || [[step_name, callable]]
108
- end
109
- end
110
- end
111
86
  end
112
87
  end
@@ -6,7 +6,40 @@ module Yaks
6
6
  end
7
7
 
8
8
  def self.all
9
- @serializers ||= {json: ->(data, env) { JSON.pretty_generate(data) }}
9
+ @serializers ||= {json: JSONWriter}
10
10
  end
11
+
12
+ module JSONWriter
13
+ extend Yaks::FP::Callable
14
+
15
+ def self.call(data, env)
16
+ JSON.pretty_generate(data)
17
+ end
18
+
19
+ def self.transitive?
20
+ true
21
+ end
22
+
23
+ def self.inverse
24
+ JSONReader
25
+ end
26
+ end
27
+
28
+ module JSONReader
29
+ extend Yaks::FP::Callable
30
+
31
+ def self.call(data, env)
32
+ JSON.parse(data)
33
+ end
34
+
35
+ def self.transitive?
36
+ true
37
+ end
38
+
39
+ def self.inverse
40
+ JSONWriter
41
+ end
42
+ end
43
+
11
44
  end
12
45
  end
data/lib/yaks/util.rb CHANGED
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  module Yaks
4
2
  module Util
5
3
  extend self
@@ -23,6 +21,14 @@ module Yaks
23
21
  keys.each_with_object({}) {|k,dest| dest[k] = hash[k] if hash.key?(k) }
24
22
  end
25
23
 
24
+ def symbolize_keys(hash)
25
+ hash.each_with_object({}) {|(k,v), hsh| hsh[k.to_sym] = v}
26
+ end
27
+
28
+ def extract_options(args)
29
+ args.last.is_a?(Hash) ? [args[0..-2], args.last] : [args, {}]
30
+ end
31
+
26
32
  # Turn what is maybe a Proc into its result (or itself)
27
33
  #
28
34
  # When input can be either a value or a proc that returns a value,
data/lib/yaks/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Yaks
2
- VERSION = '0.7.7'
2
+ VERSION = '0.8.0.alpha'
3
3
  end