praxis-blueprints 3.2 → 3.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,12 +1,10 @@
1
+ # frozen_string_literal: true
1
2
  module Praxis
2
-
3
3
  class CollectionView < View
4
- def initialize(name, schema, member_view=nil)
5
- super(name,schema)
4
+ def initialize(name, schema, member_view = nil)
5
+ super(name, schema)
6
6
 
7
- if member_view
8
- @_lazy_view = member_view
9
- end
7
+ @_lazy_view = member_view if member_view
10
8
  end
11
9
 
12
10
  def contents
@@ -17,20 +15,19 @@ module Praxis
17
15
  super
18
16
  end
19
17
 
20
- def example(context=Attributor::DEFAULT_ROOT_CONTEXT)
21
- collection = 3.times.collect do |i|
18
+ def example(context = Attributor::DEFAULT_ROOT_CONTEXT)
19
+ collection = Array.new(3) do |i|
22
20
  subcontext = context + ["at(#{i})"]
23
- self.schema.example(subcontext)
21
+ schema.example(subcontext)
24
22
  end
25
23
  opts = {}
26
24
  opts[:context] = context if context
27
25
 
28
- self.render(collection, **opts)
26
+ render(collection, **opts)
29
27
  end
30
28
 
31
29
  def describe
32
30
  super.merge(type: :collection)
33
31
  end
34
-
35
32
  end
36
33
  end
@@ -1,23 +1,27 @@
1
+ # frozen_string_literal: true
1
2
  module Praxis
2
3
  class ConfigHash < BasicObject
3
-
4
4
  attr_reader :hash
5
5
 
6
- def self.from(hash={},&block)
7
- self.new(hash,&block)
6
+ def self.from(hash = {}, &block)
7
+ new(hash, &block)
8
8
  end
9
9
 
10
- def initialize(hash={},&block)
10
+ def initialize(hash = {}, &block)
11
11
  @hash = hash
12
12
  @block = block
13
13
  end
14
14
 
15
15
  def to_hash
16
- self.instance_eval(&@block)
16
+ instance_eval(&@block)
17
17
  @hash
18
18
  end
19
19
 
20
- def method_missing(name, value, *rest, &block)
20
+ def respond_to_missing?(_method_name, _include_private = false)
21
+ true
22
+ end
23
+
24
+ def method_missing(name, value, *rest, &block) # rubocop:disable Style/MethodMissing
21
25
  if (existing = @hash[name])
22
26
  if block
23
27
  existing << [value, block]
@@ -28,13 +32,12 @@ module Praxis
28
32
  end
29
33
  end
30
34
  else
31
- if rest.any?
32
- @hash[name] = [value] + rest
33
- else
34
- @hash[name] = value
35
- end
35
+ @hash[name] = if rest.any?
36
+ [value] + rest
37
+ else
38
+ value
39
+ end
36
40
  end
37
41
  end
38
-
39
42
  end
40
43
  end
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
1
2
  module Praxis
2
3
  class FieldExpander
3
- def self.expand(object, fields=true)
4
- self.new.expand(object,fields)
4
+ def self.expand(object, fields = true)
5
+ new.expand(object, fields)
5
6
  end
6
7
 
7
8
  attr_reader :stack
@@ -11,16 +12,14 @@ module Praxis
11
12
  @stack = Hash.new do |hash, key|
12
13
  hash[key] = Set.new
13
14
  end
14
- @history = Hash.new do |hash,key|
15
- hash[key] = Hash.new
15
+ @history = Hash.new do |hash, key|
16
+ hash[key] = {}
16
17
  end
17
18
  end
18
19
 
19
- def expand(object, fields=true)
20
+ def expand(object, fields = true)
20
21
  if stack[object].include? fields
21
- if history[object].include? fields
22
- return history[object][fields]
23
- end
22
+ return history[object][fields] if history[object].include? fields
24
23
  # We should probably never get here, since we should have a record
25
24
  # of the history of an expansion if we're trying to redo it,
26
25
  # but we should also be conservative and raise here just in case.
@@ -29,13 +28,13 @@ module Praxis
29
28
  stack[object] << fields
30
29
  end
31
30
 
32
- result = if object.kind_of?(Praxis::View)
33
- self.expand_view(object, fields)
34
- elsif object.kind_of? Attributor::Attribute
35
- self.expand_type(object.type, fields)
36
- else
37
- self.expand_type(object,fields)
38
- end
31
+ result = if object.is_a?(Praxis::View)
32
+ expand_view(object, fields)
33
+ elsif object.is_a? Attributor::Attribute
34
+ expand_type(object.type, fields)
35
+ else
36
+ expand_type(object, fields)
37
+ end
39
38
 
40
39
  result
41
40
  ensure
@@ -43,38 +42,37 @@ module Praxis
43
42
  end
44
43
 
45
44
  def expand_fields(attributes, fields)
46
- raise ArgumentError, "expand_fields must be given a block" unless block_given?
45
+ raise ArgumentError, 'expand_fields must be given a block' unless block_given?
47
46
 
48
47
  unless fields == true
49
- attributes = attributes.select do |k,v|
48
+ attributes = attributes.select do |k, _v|
50
49
  fields.key?(k)
51
50
  end
52
51
  end
53
52
 
54
53
  attributes.each_with_object({}) do |(name, dumpable), hash|
55
54
  sub_fields = case fields
56
- when true
57
- true
58
- when Hash
59
- fields[name] || true
60
- end
61
- hash[name] = yield(dumpable,sub_fields)
55
+ when true
56
+ true
57
+ when Hash
58
+ fields[name] || true
59
+ end
60
+ hash[name] = yield(dumpable, sub_fields)
62
61
  end
63
62
  end
64
63
 
65
-
66
- def expand_view(object,fields=true)
67
- history[object][fields] = if object.kind_of?(Praxis::CollectionView)
68
- []
69
- else
70
- {}
71
- end
64
+ def expand_view(object, fields = true)
65
+ history[object][fields] = if object.is_a?(Praxis::CollectionView)
66
+ []
67
+ else
68
+ {}
69
+ end
72
70
 
73
71
  result = expand_fields(object.contents, fields) do |dumpable, sub_fields|
74
- self.expand(dumpable, sub_fields)
72
+ expand(dumpable, sub_fields)
75
73
  end
76
74
 
77
- if object.kind_of?(Praxis::CollectionView)
75
+ if object.is_a?(Praxis::CollectionView)
78
76
  history[object][fields] << result
79
77
  else
80
78
  history[object][fields].merge!(result)
@@ -82,41 +80,37 @@ module Praxis
82
80
  history[object][fields]
83
81
  end
84
82
 
85
-
86
- def expand_type(object,fields=true)
83
+ def expand_type(object, fields = true)
87
84
  unless object.respond_to?(:attributes)
88
85
  if object.respond_to?(:member_attribute)
89
- if history[object].include? fields
90
- return history[object][fields]
91
- end
92
- history[object][fields] = []
93
-
94
- new_fields = fields.kind_of?(Array) ? fields[0] : fields
95
-
96
- result = [self.expand(object.member_attribute.type, new_fields)]
97
- history[object][fields].push(*result)
98
-
99
- return result
86
+ return expand_with_member_attribute(object, fields)
100
87
  else
101
88
  return true
102
89
  end
103
90
  end
104
91
 
105
92
  # just include the full thing if it has no attributes
106
- if object.attributes.empty?
107
- return true
108
- end
93
+ return true if object.attributes.empty?
109
94
 
110
- if history[object].include? fields
111
- return history[object][fields]
112
- end
95
+ return history[object][fields] if history[object].include? fields
113
96
 
114
97
  history[object][fields] = {}
115
98
  result = expand_fields(object.attributes, fields) do |dumpable, sub_fields|
116
- self.expand(dumpable.type, sub_fields)
99
+ expand(dumpable.type, sub_fields)
117
100
  end
118
101
  history[object][fields].merge!(result)
119
102
  end
120
103
 
104
+ def expand_with_member_attribute(object, fields = true)
105
+ return history[object][fields] if history[object].include? fields
106
+ history[object][fields] = []
107
+
108
+ new_fields = fields.is_a?(Array) ? fields[0] : fields
109
+
110
+ result = [expand(object.member_attribute.type, new_fields)]
111
+ history[object][fields].concat(result)
112
+
113
+ result
114
+ end
121
115
  end
122
116
  end
@@ -1,7 +1,6 @@
1
+ # frozen_string_literal: true
1
2
  module Praxis
2
3
  module Finalizable
3
-
4
-
5
4
  def self.extended(klass)
6
5
  klass.module_eval do
7
6
  @finalizable = Set.new
@@ -26,13 +25,10 @@ module Praxis
26
25
  @finalized = true
27
26
  end
28
27
 
29
- def finalize!
30
- self.finalizable.reject(&:finalized?).each do |klass|
31
- klass._finalize!
32
- end
28
+ def finalize!
29
+ finalizable.reject(&:finalized?).each(&:_finalize!)
33
30
 
34
- self.finalize! unless self.finalizable.all?(&:finalized?)
31
+ finalize! unless finalizable.all?(&:finalized?)
35
32
  end
36
-
37
33
  end
38
34
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Praxis
2
3
  class Renderer
3
4
  attr_reader :include_nil
@@ -7,7 +8,7 @@ module Praxis
7
8
  attr_reader :object
8
9
  attr_reader :context
9
10
 
10
- def initialize(object,context)
11
+ def initialize(object, context)
11
12
  @object = object
12
13
  @context = context
13
14
 
@@ -19,8 +20,8 @@ module Praxis
19
20
  end
20
21
 
21
22
  def initialize(include_nil: false)
22
- @cache = Hash.new do |hash,key|
23
- hash[key] = Hash.new
23
+ @cache = Hash.new do |hash, key|
24
+ hash[key] = {}
24
25
  end
25
26
 
26
27
  @include_nil = include_nil
@@ -30,38 +31,38 @@ module Praxis
30
31
  #
31
32
  # @param [Object] object the object to render
32
33
  # @param [Hash] fields the set of fields, as from FieldExpander, to apply to each member of the collection.
33
- def render_collection(collection, member_fields, view=nil, context: Attributor::DEFAULT_ROOT_CONTEXT)
34
- render(collection,[member_fields], view, context: context)
34
+ def render_collection(collection, member_fields, view = nil, context: Attributor::DEFAULT_ROOT_CONTEXT)
35
+ render(collection, [member_fields], view, context: context)
35
36
  end
36
37
 
37
38
  # Renders an object using a given list of fields.
38
39
  #
39
40
  # @param [Object] object the object to render
40
41
  # @param [Hash] fields the correct set of fields, as from FieldExpander
41
- def render(object, fields, view=nil, context: Attributor::DEFAULT_ROOT_CONTEXT)
42
- if fields.kind_of? Array
42
+ def render(object, fields, view = nil, context: Attributor::DEFAULT_ROOT_CONTEXT)
43
+ if fields.is_a? Array
43
44
  sub_fields = fields[0]
44
45
  object.each_with_index.collect do |sub_object, i|
45
46
  sub_context = context + ["at(#{i})"]
46
47
  render(sub_object, sub_fields, view, context: sub_context)
47
48
  end
48
- elsif object.kind_of? Praxis::Blueprint
49
- @cache[object.object_id][fields.object_id] ||= _render(object,fields, view, context: context)
49
+ elsif object.is_a? Praxis::Blueprint
50
+ @cache[object.object_id][fields.object_id] ||= _render(object, fields, view, context: context)
50
51
  else
51
- _render(object,fields, view, context: context)
52
+ _render(object, fields, view, context: context)
52
53
  end
53
54
  rescue SystemStackError
54
55
  raise CircularRenderingError.new(object, context)
55
56
  end
56
57
 
57
- def _render(object, fields, view=nil, context: Attributor::DEFAULT_ROOT_CONTEXT)
58
+ def _render(object, fields, view = nil, context: Attributor::DEFAULT_ROOT_CONTEXT)
58
59
  if fields == true
59
60
  return case object
60
- when Attributor::Dumpable
61
- object.dump
62
- else
63
- object
64
- end
61
+ when Attributor::Dumpable
62
+ object.dump
63
+ else
64
+ object
65
+ end
65
66
  end
66
67
 
67
68
  notification_payload = {
@@ -70,31 +71,32 @@ module Praxis
70
71
  view: view
71
72
  }
72
73
 
73
- ActiveSupport::Notifications.instrument 'praxis.blueprint.render'.freeze, notification_payload do
74
- fields.each_with_object(Hash.new) do |(key, subfields), hash|
74
+ ActiveSupport::Notifications.instrument 'praxis.blueprint.render', notification_payload do
75
+ fields.each_with_object({}) do |(key, subfields), hash|
75
76
  begin
76
77
  value = object._get_attr(key)
77
78
  rescue => e
78
79
  raise Attributor::DumpError, context: context, name: key, type: object.class, original_exception: e
79
80
  end
80
81
 
81
- next if value.nil? && !self.include_nil
82
+ if value.nil?
83
+ hash[key] = nil if self.include_nil
84
+ next
85
+ end
82
86
 
83
87
  if subfields == true
84
88
  hash[key] = case value
85
- when Attributor::Dumpable
86
- value.dump
87
- else
88
- value
89
- end
89
+ when Attributor::Dumpable
90
+ value.dump
91
+ else
92
+ value
93
+ end
90
94
  else
91
95
  new_context = context + [key]
92
- hash[key] = self.render(value, subfields, context: new_context)
96
+ hash[key] = render(value, subfields, context: new_context)
93
97
  end
94
-
95
98
  end
96
99
  end
97
100
  end
98
-
99
101
  end
100
102
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Praxis
2
- BLUEPRINTS_VERSION = "3.2"
3
+ BLUEPRINTS_VERSION = '3.3'
3
4
  end
@@ -1,5 +1,5 @@
1
+ # frozen_string_literal: true
1
2
  module Praxis
2
-
3
3
  class View
4
4
  attr_reader :schema
5
5
  attr_reader :contents
@@ -17,7 +17,7 @@ module Praxis
17
17
 
18
18
  def contents
19
19
  if @block
20
- self.instance_eval(&@block)
20
+ instance_eval(&@block)
21
21
  @block = nil
22
22
  end
23
23
 
@@ -26,32 +26,31 @@ module Praxis
26
26
 
27
27
  def expanded_fields
28
28
  @expanded_fields ||= begin
29
- self.contents # force evaluation of the contents
29
+ contents # force evaluation of the contents
30
30
  FieldExpander.expand(self)
31
31
  end
32
32
  end
33
33
 
34
34
  def render(object, context: Attributor::DEFAULT_ROOT_CONTEXT, renderer: Renderer.new)
35
- renderer.render(object, self.expanded_fields, context: context)
35
+ renderer.render(object, expanded_fields, context: context)
36
36
  end
37
37
 
38
- alias_method :to_hash, :render # Why did we need this again?
39
-
38
+ alias to_hash render # Why did we need this again?
40
39
 
41
40
  def attribute(name, **opts, &block)
42
- raise AttributorException, "Attribute names must be symbols, got: #{name.inspect}" unless name.kind_of? ::Symbol
41
+ raise AttributorException, "Attribute names must be symbols, got: #{name.inspect}" unless name.is_a? ::Symbol
43
42
 
44
- attribute = self.schema.attributes.fetch(name) do
45
- raise "Displaying :#{name} is not allowed in view :#{self.name} of #{self.schema}. This attribute does not exist in the mediatype"
43
+ attribute = schema.attributes.fetch(name) do
44
+ raise "Displaying :#{name} is not allowed in view :#{self.name} of #{schema}. This attribute does not exist in the mediatype"
46
45
  end
47
46
 
48
47
  if block_given?
49
48
  type = attribute.type
50
49
  @contents[name] = if type < Attributor::Collection
51
- CollectionView.new(name, type.member_attribute.type, &block)
52
- else
53
- View.new(name, attribute, &block)
54
- end
50
+ CollectionView.new(name, type.member_attribute.type, &block)
51
+ else
52
+ View.new(name, attribute, &block)
53
+ end
55
54
  else
56
55
  type = attribute.type
57
56
  if type < Attributor::Collection
@@ -59,38 +58,36 @@ module Praxis
59
58
  type = type.member_attribute.type
60
59
  end
61
60
 
62
-
63
61
  if type < Praxis::Blueprint
64
62
  view_name = opts[:view] || :default
65
63
  view = type.views.fetch(view_name) do
66
64
  raise "view with name '#{view_name.inspect}' is not defined in #{type}"
67
65
  end
68
- if is_collection
69
- @contents[name] = Praxis::CollectionView.new(view_name, type, view)
70
- else
71
- @contents[name] = view
72
- end
66
+ @contents[name] = if is_collection
67
+ Praxis::CollectionView.new(view_name, type, view)
68
+ else
69
+ view
70
+ end
73
71
  else
74
- @contents[name] = attribute #, opts]
72
+ @contents[name] = attribute # , opts]
75
73
  end
76
74
  end
77
-
78
75
  end
79
76
 
80
- def example(context=Attributor::DEFAULT_ROOT_CONTEXT)
81
- object = self.schema.example(context)
77
+ def example(context = Attributor::DEFAULT_ROOT_CONTEXT)
78
+ object = schema.example(context)
82
79
  opts = {}
83
80
  opts[:context] = context if context
84
- self.render(object, opts)
81
+ render(object, opts)
85
82
  end
86
83
 
87
84
  def describe
88
85
  # TODO: for now we are just return the first level keys
89
86
  view_attributes = {}
90
87
 
91
- self.contents.each do |k,dumpable|
88
+ contents.each do |k, dumpable|
92
89
  inner_desc = {}
93
- if dumpable.kind_of?(Praxis::View)
90
+ if dumpable.is_a?(Praxis::View)
94
91
  inner_desc[:view] = dumpable.name if dumpable.name
95
92
  end
96
93
  view_attributes[k] = inner_desc
@@ -98,7 +95,5 @@ module Praxis
98
95
 
99
96
  { attributes: view_attributes, type: :standard }
100
97
  end
101
-
102
-
103
98
  end
104
99
  end