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