blueprinter-rb 1.1.1 → 1.2.0
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.
- checksums.yaml +4 -4
- data/README.md +1020 -0
- data/lib/blueprinter/base.rb +8 -15
- data/lib/blueprinter/configuration.rb +3 -2
- data/lib/blueprinter/deprecation.rb +3 -3
- data/lib/blueprinter/empty_types.rb +5 -9
- data/lib/blueprinter/extractor.rb +4 -4
- data/lib/blueprinter/extractors/association_extractor.rb +3 -2
- data/lib/blueprinter/extractors/block_extractor.rb +1 -1
- data/lib/blueprinter/extractors/public_send_extractor.rb +1 -1
- data/lib/blueprinter/field.rb +42 -47
- data/lib/blueprinter/formatters/date_time_formatter.rb +1 -1
- data/lib/blueprinter/helpers/base_helpers.rb +15 -13
- data/lib/blueprinter/transformer.rb +2 -2
- data/lib/blueprinter/version.rb +1 -1
- data/lib/blueprinter/view.rb +6 -6
- data/lib/blueprinter/view_collection.rb +11 -6
- data/lib/generators/blueprinter/blueprint_generator.rb +35 -48
- metadata +8 -146
data/lib/blueprinter/base.rb
CHANGED
@@ -60,7 +60,7 @@ module Blueprinter
|
|
60
60
|
name,
|
61
61
|
extractor,
|
62
62
|
self,
|
63
|
-
block: block
|
63
|
+
block: block
|
64
64
|
)
|
65
65
|
end
|
66
66
|
|
@@ -125,7 +125,7 @@ module Blueprinter
|
|
125
125
|
options.fetch(:name) { method },
|
126
126
|
options.fetch(:extractor) { Blueprinter.configuration.extractor_default.new },
|
127
127
|
self,
|
128
|
-
options.merge(block: block)
|
128
|
+
options.merge(block: block)
|
129
129
|
)
|
130
130
|
end
|
131
131
|
|
@@ -165,7 +165,7 @@ module Blueprinter
|
|
165
165
|
method,
|
166
166
|
options.merge(
|
167
167
|
association: true,
|
168
|
-
extractor: options.fetch(:extractor) { AssociationExtractor.new }
|
168
|
+
extractor: options.fetch(:extractor) { AssociationExtractor.new }
|
169
169
|
),
|
170
170
|
&block
|
171
171
|
)
|
@@ -254,9 +254,7 @@ module Blueprinter
|
|
254
254
|
#
|
255
255
|
# @api private
|
256
256
|
def self.prepare(object, view_name:, local_options:, root: nil, meta: nil)
|
257
|
-
unless view_collection.
|
258
|
-
raise BlueprinterError, "View '#{view_name}' is not defined"
|
259
|
-
end
|
257
|
+
raise BlueprinterError, "View '#{view_name}' is not defined" unless view_collection.view? view_name
|
260
258
|
|
261
259
|
data = prepare_data(object, view_name, local_options)
|
262
260
|
prepend_root_and_meta(data, root, meta)
|
@@ -281,7 +279,6 @@ module Blueprinter
|
|
281
279
|
end
|
282
280
|
end
|
283
281
|
|
284
|
-
|
285
282
|
# Specify one transformer to be included for serialization.
|
286
283
|
# Takes a class which extends Blueprinter::Transformer
|
287
284
|
#
|
@@ -317,7 +314,6 @@ module Blueprinter
|
|
317
314
|
current_view.add_transformer(transformer)
|
318
315
|
end
|
319
316
|
|
320
|
-
|
321
317
|
# Specify another view that should be mixed into the current view.
|
322
318
|
#
|
323
319
|
# @param view_name [Symbol] the view to mix into the current view.
|
@@ -340,7 +336,6 @@ module Blueprinter
|
|
340
336
|
current_view.include_view(view_name)
|
341
337
|
end
|
342
338
|
|
343
|
-
|
344
339
|
# Specify additional views that should be mixed into the current view.
|
345
340
|
#
|
346
341
|
# @param view_name [Array<Symbol>] the views to mix into the current view.
|
@@ -363,12 +358,10 @@ module Blueprinter
|
|
363
358
|
#
|
364
359
|
# @return [Array<Symbol>] an array of view names.
|
365
360
|
|
366
|
-
|
367
361
|
def self.include_views(*view_names)
|
368
362
|
current_view.include_views(view_names)
|
369
363
|
end
|
370
364
|
|
371
|
-
|
372
365
|
# Exclude a field that was mixed into the current view.
|
373
366
|
#
|
374
367
|
# @param field_name [Symbol] the field to exclude from the current view.
|
@@ -446,13 +439,13 @@ module Blueprinter
|
|
446
439
|
# end
|
447
440
|
# end
|
448
441
|
#
|
449
|
-
# ExampleBlueprint.
|
450
|
-
# ExampleBlueprint.
|
442
|
+
# ExampleBlueprint.view?(:custom) => true
|
443
|
+
# ExampleBlueprint.view?(:doesnt_exist) => false
|
451
444
|
#
|
452
445
|
# @return [Boolean] a boolean value indicating if the view is
|
453
446
|
# supported by this Blueprint.
|
454
|
-
def self.
|
455
|
-
view_collection.
|
447
|
+
def self.view?(view_name)
|
448
|
+
view_collection.view? view_name
|
456
449
|
end
|
457
450
|
end
|
458
451
|
end
|
@@ -2,9 +2,10 @@
|
|
2
2
|
|
3
3
|
module Blueprinter
|
4
4
|
class Configuration
|
5
|
-
attr_accessor :association_default, :datetime_format, :deprecations, :field_default, :generator, :if, :method,
|
5
|
+
attr_accessor :association_default, :datetime_format, :deprecations, :field_default, :generator, :if, :method,
|
6
|
+
:sort_fields_by, :unless, :extractor_default, :default_transformers, :custom_array_like_classes
|
6
7
|
|
7
|
-
VALID_CALLABLES = %i
|
8
|
+
VALID_CALLABLES = %i[if unless].freeze
|
8
9
|
|
9
10
|
def initialize
|
10
11
|
@deprecations = :stderror
|
@@ -4,8 +4,8 @@
|
|
4
4
|
module Blueprinter
|
5
5
|
class Deprecation
|
6
6
|
class << self
|
7
|
-
VALID_BEHAVIORS = %i
|
8
|
-
MESSAGE_PREFIX =
|
7
|
+
VALID_BEHAVIORS = %i[silence stderror raise].freeze
|
8
|
+
MESSAGE_PREFIX = '[DEPRECATION::WARNING] Blueprinter:'
|
9
9
|
|
10
10
|
def report(message)
|
11
11
|
full_msg = qualified_message(message)
|
@@ -28,7 +28,7 @@ module Blueprinter
|
|
28
28
|
|
29
29
|
def behavior
|
30
30
|
configured = Blueprinter.configuration.deprecations
|
31
|
-
return configured
|
31
|
+
return configured if VALID_BEHAVIORS.include?(configured)
|
32
32
|
|
33
33
|
:stderror
|
34
34
|
end
|
@@ -3,12 +3,13 @@
|
|
3
3
|
require_relative 'helpers/type_helpers'
|
4
4
|
|
5
5
|
module Blueprinter
|
6
|
-
EMPTY_COLLECTION =
|
7
|
-
EMPTY_HASH =
|
8
|
-
EMPTY_STRING =
|
6
|
+
EMPTY_COLLECTION = 'empty_collection'
|
7
|
+
EMPTY_HASH = 'empty_hash'
|
8
|
+
EMPTY_STRING = 'empty_string'
|
9
9
|
|
10
10
|
module EmptyTypes
|
11
11
|
include TypeHelpers
|
12
|
+
|
12
13
|
private
|
13
14
|
|
14
15
|
def use_default_value?(value, empty_type)
|
@@ -20,12 +21,7 @@ module Blueprinter
|
|
20
21
|
when Blueprinter::EMPTY_HASH
|
21
22
|
value.is_a?(Hash) && value.empty?
|
22
23
|
when Blueprinter::EMPTY_STRING
|
23
|
-
value.to_s ==
|
24
|
-
else
|
25
|
-
Blueprinter::Deprecation.report(
|
26
|
-
"Invalid empty type '#{empty_type}' received. Blueprinter will raise an error in the next major version."\
|
27
|
-
"Must be one of [nil, Blueprinter::EMPTY_COLLECTION, Blueprinter::EMPTY_HASH, Blueprinter::EMPTY_STRING]"
|
28
|
-
)
|
24
|
+
value.to_s == ''
|
29
25
|
end
|
30
26
|
end
|
31
27
|
end
|
@@ -2,12 +2,12 @@
|
|
2
2
|
|
3
3
|
module Blueprinter
|
4
4
|
class Extractor
|
5
|
-
def extract(_field_name, _object, _local_options, _options={})
|
6
|
-
|
5
|
+
def extract(_field_name, _object, _local_options, _options = {})
|
6
|
+
raise NotImplementedError, 'An Extractor must implement #extract'
|
7
7
|
end
|
8
8
|
|
9
|
-
def self.extract(field_name, object, local_options, options={})
|
10
|
-
|
9
|
+
def self.extract(field_name, object, local_options, options = {})
|
10
|
+
new.extract(field_name, object, local_options, options)
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -9,12 +9,13 @@ module Blueprinter
|
|
9
9
|
@extractor = Blueprinter.configuration.extractor_default.new
|
10
10
|
end
|
11
11
|
|
12
|
-
def extract(association_name, object, local_options, options={})
|
13
|
-
options_without_default = options.reject { |k,_|
|
12
|
+
def extract(association_name, object, local_options, options = {})
|
13
|
+
options_without_default = options.reject { |k, _| %i[default default_if].include?(k) }
|
14
14
|
# Merge in assocation options hash
|
15
15
|
local_options = local_options.merge(options[:options]) if options[:options].is_a?(Hash)
|
16
16
|
value = @extractor.extract(association_name, object, local_options, options_without_default)
|
17
17
|
return default_value(options) if use_default_value?(value, options[:default_if])
|
18
|
+
|
18
19
|
view = options[:view] || :default
|
19
20
|
blueprint = association_blueprint(options[:blueprint], value)
|
20
21
|
blueprint.prepare(value, view_name: view, local_options: local_options)
|
data/lib/blueprinter/field.rb
CHANGED
@@ -1,65 +1,60 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# @api private
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
4
|
+
module Blueprinter
|
5
|
+
class Field
|
6
|
+
attr_reader :method, :name, :extractor, :options, :blueprint
|
7
|
+
|
8
|
+
def initialize(method, name, extractor, blueprint, options = {})
|
9
|
+
@method = method
|
10
|
+
@name = name
|
11
|
+
@extractor = extractor
|
12
|
+
@blueprint = blueprint
|
13
|
+
@options = options
|
14
|
+
end
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
|
16
|
+
def extract(object, local_options)
|
17
|
+
extractor.extract(method, object, local_options, options)
|
18
|
+
end
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
unless_callable && unless_callable.call(field_name, object, local_options)
|
21
|
-
end
|
20
|
+
def skip?(field_name, object, local_options)
|
21
|
+
return true if if_callable && !if_callable.call(field_name, object, local_options)
|
22
22
|
|
23
|
-
|
23
|
+
unless_callable && unless_callable.call(field_name, object, local_options)
|
24
|
+
end
|
24
25
|
|
25
|
-
|
26
|
-
return @if_callable if defined?(@if_callable)
|
27
|
-
@if_callable = callable_from(:if)
|
28
|
-
end
|
26
|
+
private
|
29
27
|
|
30
|
-
|
31
|
-
|
32
|
-
@unless_callable = callable_from(:unless)
|
33
|
-
end
|
28
|
+
def if_callable
|
29
|
+
return @if_callable if defined?(@if_callable)
|
34
30
|
|
35
|
-
|
36
|
-
|
31
|
+
@if_callable = callable_from(:if)
|
32
|
+
end
|
37
33
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
callable
|
34
|
+
def unless_callable
|
35
|
+
return @unless_callable if defined?(@unless_callable)
|
36
|
+
|
37
|
+
@unless_callable = callable_from(:unless)
|
43
38
|
end
|
44
|
-
end
|
45
39
|
|
46
|
-
|
47
|
-
|
40
|
+
def callable_from(condition)
|
41
|
+
config = Blueprinter.configuration
|
48
42
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
43
|
+
# Use field-level callable, or when not defined, try global callable
|
44
|
+
tmp = if options.key?(condition)
|
45
|
+
options.fetch(condition)
|
46
|
+
elsif config.valid_callable?(condition)
|
47
|
+
config.public_send(condition)
|
48
|
+
end
|
55
49
|
|
56
|
-
|
50
|
+
return false unless tmp
|
57
51
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
52
|
+
case tmp
|
53
|
+
when Proc then tmp
|
54
|
+
when Symbol then blueprint.method(tmp)
|
55
|
+
else
|
56
|
+
raise ArgumentError, "#{tmp.class} is passed to :#{condition}"
|
57
|
+
end
|
63
58
|
end
|
64
59
|
end
|
65
60
|
end
|
@@ -26,7 +26,7 @@ module Blueprinter
|
|
26
26
|
when Proc then format.call(value)
|
27
27
|
when String then value.strftime(format)
|
28
28
|
else
|
29
|
-
raise InvalidDateTimeFormatterError,
|
29
|
+
raise InvalidDateTimeFormatterError, "Cannot format DateTime object with invalid formatter: #{format.class}"
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
@@ -35,7 +35,8 @@ module Blueprinter
|
|
35
35
|
|
36
36
|
def prepend_root_and_meta(data, root, meta)
|
37
37
|
return data unless root
|
38
|
-
|
38
|
+
|
39
|
+
ret = { root => data }
|
39
40
|
meta ? ret.merge!(meta: meta) : ret
|
40
41
|
end
|
41
42
|
|
@@ -46,6 +47,7 @@ module Blueprinter
|
|
46
47
|
def object_to_hash(object, view_name:, local_options:)
|
47
48
|
result_hash = view_collection.fields_for(view_name).each_with_object({}) do |field, hash|
|
48
49
|
next if field.skip?(field.name, object, local_options)
|
50
|
+
|
49
51
|
hash[field.name] = field.extract(object, local_options)
|
50
52
|
end
|
51
53
|
view_collection.transformers(view_name).each do |transformer|
|
@@ -59,9 +61,9 @@ module Blueprinter
|
|
59
61
|
when String, Symbol
|
60
62
|
# no-op
|
61
63
|
when NilClass
|
62
|
-
raise BlueprinterError,
|
64
|
+
raise BlueprinterError, 'meta requires a root to be passed' if meta
|
63
65
|
else
|
64
|
-
raise BlueprinterError,
|
66
|
+
raise BlueprinterError, 'root should be one of String, Symbol, NilClass'
|
65
67
|
end
|
66
68
|
end
|
67
69
|
|
@@ -71,10 +73,10 @@ module Blueprinter
|
|
71
73
|
|
72
74
|
def validate_blueprint!(blueprint, method)
|
73
75
|
validate_presence_of_blueprint!(blueprint)
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
76
|
+
return if dynamic_blueprint?(blueprint)
|
77
|
+
|
78
|
+
validate_blueprint_has_ancestors!(blueprint, method)
|
79
|
+
validate_blueprint_has_blueprinter_base_ancestor!(blueprint, method)
|
78
80
|
end
|
79
81
|
|
80
82
|
def validate_presence_of_blueprint!(blueprint)
|
@@ -86,10 +88,10 @@ module Blueprinter
|
|
86
88
|
# it means it, at the very least, does not have Blueprinter::Base as
|
87
89
|
# one of its ancestor classes (e.g: Hash) and thus an error should
|
88
90
|
# be raised.
|
89
|
-
|
90
|
-
|
91
|
+
return if blueprint.respond_to?(:ancestors)
|
92
|
+
|
93
|
+
raise BlueprinterError, "Blueprint provided for #{association_name} " \
|
91
94
|
'association is not valid.'
|
92
|
-
end
|
93
95
|
end
|
94
96
|
|
95
97
|
def validate_blueprint_has_blueprinter_base_ancestor!(blueprint, association_name)
|
@@ -98,9 +100,9 @@ module Blueprinter
|
|
98
100
|
return if blueprint.ancestors.include? Blueprinter::Base
|
99
101
|
|
100
102
|
# Raise error describing what's wrong.
|
101
|
-
raise BlueprinterError, "Class #{blueprint.name} does not inherit from "\
|
102
|
-
|
103
|
-
|
103
|
+
raise BlueprinterError, "Class #{blueprint.name} does not inherit from " \
|
104
|
+
'Blueprinter::Base and is not a valid Blueprinter ' \
|
105
|
+
"for #{association_name} association."
|
104
106
|
end
|
105
107
|
|
106
108
|
def jsonify(blob)
|
@@ -4,11 +4,11 @@ module Blueprinter
|
|
4
4
|
# @api private
|
5
5
|
class Transformer
|
6
6
|
def transform(_result_hash, _primary_obj, _options = {})
|
7
|
-
|
7
|
+
raise NotImplementedError, 'A Transformer must implement #transform'
|
8
8
|
end
|
9
9
|
|
10
10
|
def self.transform(result_hash, primary_obj, options = {})
|
11
|
-
|
11
|
+
new.transform(result_hash, primary_obj, options)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
data/lib/blueprinter/version.rb
CHANGED
data/lib/blueprinter/view.rb
CHANGED
@@ -20,14 +20,14 @@ module Blueprinter
|
|
20
20
|
view_transformers.empty? ? Blueprinter.configuration.default_transformers : view_transformers
|
21
21
|
end
|
22
22
|
|
23
|
-
def track_definition_order(method,
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
def track_definition_order(method, viewable: true)
|
24
|
+
return unless @sort_by_definition
|
25
|
+
|
26
|
+
@definition_order << DefinitionPlaceholder.new(method, viewable)
|
27
27
|
end
|
28
28
|
|
29
29
|
def inherit(view)
|
30
|
-
view.fields.
|
30
|
+
view.fields.each_value do |field|
|
31
31
|
self << field
|
32
32
|
end
|
33
33
|
|
@@ -71,7 +71,7 @@ module Blueprinter
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def <<(field)
|
74
|
-
track_definition_order(field.name,false)
|
74
|
+
track_definition_order(field.name, viewable: false)
|
75
75
|
fields[field.name] = field
|
76
76
|
end
|
77
77
|
end
|
@@ -4,6 +4,7 @@ module Blueprinter
|
|
4
4
|
# @api private
|
5
5
|
class ViewCollection
|
6
6
|
attr_reader :views, :sort_by_definition
|
7
|
+
|
7
8
|
def initialize
|
8
9
|
@views = {
|
9
10
|
identifier: View.new(:identifier),
|
@@ -18,8 +19,8 @@ module Blueprinter
|
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
21
|
-
def
|
22
|
-
views.
|
22
|
+
def view?(view_name)
|
23
|
+
views.key? view_name
|
23
24
|
end
|
24
25
|
|
25
26
|
def fields_for(view_name)
|
@@ -28,8 +29,8 @@ module Blueprinter
|
|
28
29
|
fields, excluded_fields = sortable_fields(view_name)
|
29
30
|
sorted_fields = sort_by_definition ? sort_by_def(view_name, fields) : fields.values.sort_by(&:name)
|
30
31
|
|
31
|
-
(identifier_fields + sorted_fields).tap do |
|
32
|
-
|
32
|
+
(identifier_fields + sorted_fields).tap do |fields_array|
|
33
|
+
fields_array.reject! { |field| excluded_fields.include?(field.name) }
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
@@ -69,7 +70,9 @@ module Blueprinter
|
|
69
70
|
# select and order members of fields according to traversal of the definition_orders
|
70
71
|
def sort_by_def(view_name, fields)
|
71
72
|
ordered_fields = {}
|
72
|
-
views[:default].definition_order.each
|
73
|
+
views[:default].definition_order.each do |definition|
|
74
|
+
add_to_ordered_fields(ordered_fields, definition, fields, view_name)
|
75
|
+
end
|
73
76
|
ordered_fields.values
|
74
77
|
end
|
75
78
|
|
@@ -78,7 +81,9 @@ module Blueprinter
|
|
78
81
|
def add_to_ordered_fields(ordered_fields, definition, fields, view_name_filter = nil)
|
79
82
|
if definition.view?
|
80
83
|
if view_name_filter.nil? || view_name_filter == definition.name
|
81
|
-
views[definition.name].definition_order.each
|
84
|
+
views[definition.name].definition_order.each do |defined|
|
85
|
+
add_to_ordered_fields(ordered_fields, defined, fields)
|
86
|
+
end
|
82
87
|
end
|
83
88
|
else
|
84
89
|
ordered_fields[definition.name] = fields[definition.name]
|
@@ -3,39 +3,31 @@
|
|
3
3
|
module Blueprinter
|
4
4
|
module Generators
|
5
5
|
class BlueprintGenerator < ::Rails::Generators::NamedBase
|
6
|
-
desc
|
6
|
+
desc 'Generates blueprint for ActiveRecord model with the given NAME.'
|
7
7
|
|
8
8
|
attr_accessor :options
|
9
9
|
|
10
|
-
source_root File.expand_path(
|
10
|
+
source_root File.expand_path('templates', __dir__)
|
11
11
|
|
12
|
+
class_option :blueprints_dir, default: 'app/blueprints', desc: 'path to new blueprint', aliases: '-d'
|
12
13
|
|
14
|
+
class_option :identifier, default: nil,
|
15
|
+
desc: 'Add an identifer to the generated blueprint, either uses :id or your specified value', aliases: '-i', banner: 'id'
|
13
16
|
|
14
|
-
class_option :
|
17
|
+
class_option :fields, type: :array, default: [], desc: 'Manually add specified fields'
|
15
18
|
|
19
|
+
class_option :detect_fields, type: :boolean, default: false,
|
20
|
+
desc: 'Introspect on the model to set fields in the generated blueprint. Will be merged with any manually specified'
|
16
21
|
|
22
|
+
class_option :associations, type: :array, default: [], desc: 'Manually add specified associations', aliases: '-a'
|
17
23
|
|
18
|
-
class_option :
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
class_option :fields, type: :array, default: [], desc: "Manually add specified fields"
|
23
|
-
|
24
|
-
class_option :detect_fields, type: :boolean, default: false, desc: "Introspect on the model to set fields in the generated blueprint. Will be merged with any manually specified"
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
class_option :associations, type: :array, default: [], desc: "Manually add specified associations", aliases: "-a"
|
29
|
-
|
30
|
-
class_option :detect_associations, type: :boolean, default: false, desc: "Introspect on the model to set associations in the generated blueprint. Will be merged with any manually specified"
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
class_option :wrap_at, type: :numeric, default: 80, desc: "Maximum length of generated fields line", aliases: "-w"
|
35
|
-
|
36
|
-
class_option :indentation, type: :string, default: "two", desc: "Indentation of generated file", banner: "two|four|tab"
|
24
|
+
class_option :detect_associations, type: :boolean, default: false,
|
25
|
+
desc: 'Introspect on the model to set associations in the generated blueprint. Will be merged with any manually specified'
|
37
26
|
|
27
|
+
class_option :wrap_at, type: :numeric, default: 80, desc: 'Maximum length of generated fields line', aliases: '-w'
|
38
28
|
|
29
|
+
class_option :indentation, type: :string, default: 'two', desc: 'Indentation of generated file',
|
30
|
+
banner: 'two|four|tab'
|
39
31
|
|
40
32
|
remove_class_option :skip_namespace
|
41
33
|
|
@@ -44,30 +36,28 @@ module Blueprinter
|
|
44
36
|
end
|
45
37
|
|
46
38
|
def create_blueprint
|
47
|
-
template
|
39
|
+
template 'blueprint.rb', File.join(path, "#{file_path}_blueprint.rb")
|
48
40
|
end
|
49
41
|
|
50
|
-
|
51
|
-
|
52
42
|
private
|
53
43
|
|
54
44
|
def path
|
55
|
-
options[
|
45
|
+
options['blueprints_dir']
|
56
46
|
end
|
57
47
|
|
58
48
|
def identifier_symbol
|
59
|
-
|
60
|
-
|
61
|
-
|
49
|
+
return unless options['identifier']
|
50
|
+
|
51
|
+
options['identifier'] == 'identifier' ? :id : options['identifier']
|
62
52
|
end
|
63
53
|
|
64
54
|
def fields
|
65
|
-
fs = if options[
|
66
|
-
Array.new(options[
|
55
|
+
fs = if options['detect_fields']
|
56
|
+
Array.new(options['fields']).concat(introspected_fields)
|
67
57
|
else
|
68
|
-
options[
|
58
|
+
options['fields']
|
69
59
|
end
|
70
|
-
fs.reject
|
60
|
+
fs.reject(&:blank?).uniq
|
71
61
|
end
|
72
62
|
|
73
63
|
def introspected_fields
|
@@ -77,30 +67,29 @@ module Blueprinter
|
|
77
67
|
# split at wrap_at chars, two indentations
|
78
68
|
def formatted_fields
|
79
69
|
two_indents = indent * 2
|
80
|
-
fields_string = fields.
|
81
|
-
if
|
70
|
+
fields_string = fields.each_with_object([]) do |f, memo|
|
71
|
+
if memo.last.nil?
|
72
|
+
memo << " :#{f},"
|
73
|
+
else
|
82
74
|
now = "#{memo.last} :#{f},"
|
83
|
-
if now.length > options[
|
75
|
+
if now.length > options['wrap_at'].to_i
|
84
76
|
memo << ":#{f},"
|
85
77
|
else
|
86
78
|
memo[memo.length - 1] = now
|
87
79
|
end
|
88
|
-
else
|
89
|
-
memo << " :#{f},"
|
90
80
|
end
|
91
|
-
memo
|
92
81
|
end.join("\n#{two_indents}")
|
93
82
|
|
94
|
-
fields_string[0,fields_string.length - 1]
|
83
|
+
fields_string[0, fields_string.length - 1]
|
95
84
|
end
|
96
85
|
|
97
86
|
def associations
|
98
|
-
as = if options[
|
99
|
-
Array.new(options[
|
87
|
+
as = if options['detect_associations']
|
88
|
+
Array.new(options['associations']).concat(introspected_associations.keys)
|
100
89
|
else
|
101
|
-
options[
|
90
|
+
options['associations']
|
102
91
|
end
|
103
|
-
as.reject
|
92
|
+
as.reject(&:blank?).uniq
|
104
93
|
end
|
105
94
|
|
106
95
|
def introspected_associations
|
@@ -114,15 +103,13 @@ module Blueprinter
|
|
114
103
|
def association_class(association_name)
|
115
104
|
introspected_name = if introspected_associations[association_name].respond_to?(:klass)
|
116
105
|
introspected_associations[association_name].klass.to_s
|
117
|
-
else
|
118
|
-
nil
|
119
106
|
end
|
120
107
|
"#{introspected_name || association_name.camelcase}Blueprint"
|
121
108
|
end
|
122
109
|
|
123
110
|
def indent
|
124
|
-
user_intended = {two:
|
125
|
-
user_intended.nil? ?
|
111
|
+
user_intended = { two: ' ', four: ' ', tab: "\t" }[options['indentation'].intern]
|
112
|
+
user_intended.nil? ? ' ' : user_intended
|
126
113
|
end
|
127
114
|
end
|
128
115
|
end
|