./lib/json-exporter/base.rb in json-exporter-0.4.1 vs ./lib/json-exporter/base.rb in json-exporter-0.4.3
- old
+ new
@@ -1,136 +1,120 @@
class JsonExporter
EXPORTERS ||= {}
- FILTERS ||= {b:{}, a:{}}
- OPTS ||= {}
+ FILTERS ||= {before:{}, after:{}}
+ INFLECTOR ||= Dry::Inflector.new
class << self
- def define *args, &block
- if args.first.is_a?(Hash)
- name, opts = nil, args[0]
- else
- name, opts = args[0], args[1]
- end
+ def define name = nil, &block
+ name = name ? "#{INFLECTOR.classify(name)}#{to_s}" : to_s
- name = name ? name.to_s.classify : to_s
- opts ||= {}
-
EXPORTERS[name] = block
end
- def export name, opts={}
- new(name, opts).render
+ def export name, opts = nil
+ new(name, opts || {}).render
end
def before &block
- FILTERS[:b][to_s] = block
+ __define_filter :before, &block
end
def after &block
- FILTERS[:a][to_s] = block
+ __define_filter :after, &block
end
- def disable_wia!
- OPTS[:wia] = false
+ def __define_filter name, &block
+ define_method name do
+ super() if self.class != JsonExporter
+ instance_exec &block
+ end
end
end
###
- attr_accessor :response, :model, :opts, :user
+ attr_accessor :json, :model, :opts
- def initialize model, opts={}
+ alias :response :json
+
+ def initialize model, opts = {}
if model.is_a?(String) || model.is_a?(Symbol)
raise ArgumentError, 'model argument is not model instance (it is %s)' % model.class
end
opts[:export_depth] ||= 2 # 2 is default depth. if we encounter nested recursive exports, will go only to depth 2
opts[:current_depth] ||= 0
opts[:current_depth] += 1
- @user = opts[:user]
- @model = model
- @opts = opts.to_hwia
- @block = exporter_find_class
- @response = OPTS[:wia] == false ? {} : {}.to_hwia
+ @model = model
+ @opts = opts.to_hwia
+ @block = __find_exporter
+ @json = {}
end
def render
- exporter_apply_filters :b
+ before
instance_exec &@block
- exporter_apply_filters :a
+ after
- @response
+ @json
end
+ def before; end
+
+ def after; end
+
private
# export object
# export :org_users, key: :users
- def export name, opts = {}
+ def export name, local_opts = {}
return if @opts[:current_depth] > @opts[:export_depth]
if name.is_a?(Symbol)
name, cmodel = name, @model.send(name)
if cmodel.respond_to?(:all) && cmodel.respond_to?(:first)
cmodel = cmodel.all.map { |el| JsonExporter.export(el, @opts.dup) }
end
else
- name, cmodel = name.class.to_s.underscore.to_sym, name
+ underscored = INFLECTOR.underscore(name.class.to_s).to_sym
+ name, cmodel = underscored, name
end
- @response[opts[:key] || name] =
- if [Array].include?(cmodel.class)
- cmodel
- elsif cmodel.nil?
- nil
- else
- JsonExporter.export(cmodel, @opts)
- end
+ @json[name] = if [Array].include?(cmodel.class)
+ cmodel
+ elsif cmodel.nil?
+ nil
+ else
+ new_opts = local_opts.merge(export_depth: @opts[:export_depth], current_depth: @opts[:current_depth])
+ self.class.new(cmodel, new_opts).render
+ end
end
# add property to exporter
- def property name, data=:_undefined
+ def property name, data = :_undefined, &block
if block_given?
hash_data = {}
- data = yield hash_data
+ data = instance_exec hash_data, &block
data = hash_data if hash_data.keys.first
elsif data == :_undefined
data = @model.send(name)
end
- @response[name] = data unless data.nil?
+ @json[name] = data unless data.nil?
end
alias :prop :property
- # finds versioned exporter
- def exporter_find_class version=nil
- exporter =
- if @opts[:exporter]
- @opts[:exporter].to_s.classify
- elsif self.class == JsonExporter
- # JsonExporter.define User do
- @opts[:exporter] ? @opts[:exporter].to_s.classify : model.class
- else
- # class FooExporter< JsonExporter
- self.class
- end
+ def __find_exporter version = nil
+ base = INFLECTOR.classify @opts[:exporter] || model.class.to_s
+ exporter = self.class.to_s
- EXPORTERS[exporter.to_s] || EXPORTERS[model.class.to_s] || raise('Exporter "%s" (:%s) not found' % [exporter, exporter.to_s.underscore])
- end
-
- def exporter_apply_filters kind
- for klass in self.class.ancestors.reverse.map(&:to_s)
- if filter = FILTERS[kind][klass]
- instance_exec(&filter) if filter
- end
+ self.class.ancestors.map(&:to_s).each do |klass|
+ block = EXPORTERS[[base, klass].join] || EXPORTERS[klass]
+ return block if block
end
- end
- def merge object
- object.each do |k, v|
- prop k.to_sym, v
- end
+ raise(%[Exporter for class "#{base}" not found.])
end
end