./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