Class: Webservice::ResponseHandler

Inherits:
Object
  • Object
show all
Defined in:
lib/webservice/base/response_handler.rb

Defined Under Namespace

Classes: Tabular

Instance Method Summary collapse

Constructor Details

#initialize(app) ⇒ ResponseHandler

Returns a new instance of ResponseHandler.



11
12
13
# File 'lib/webservice/base/response_handler.rb', line 11

def initialize( app )
  @app = app
end

Instance Method Details

#as_json(obj, opts = {}) ⇒ Object



179
180
181
182
183
184
185
186
187
188
189
# File 'lib/webservice/base/response_handler.rb', line 179

def as_json( obj, opts={} )
  if obj.respond_to? :as_json_v3     ## try (our own) serializer first
    obj.as_json_v3
  elsif obj.respond_to? :as_json_v2     ## try (our own) serializer first
    obj.as_json_v2
  elsif obj.respond_to? :as_json     ## try (activerecord) serializer
    obj.as_json
  else
    obj   ## just try/use as is
  end
end

#as_tabular(obj, opts = {}) ⇒ Object

auto-generate/convert “magic”



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/webservice/base/response_handler.rb', line 98

def as_tabular( obj, opts={} )
   headers = []
   headers_clone = []  ## keep an unmodified (e.g. with symbols not string) headers/keys clone
   rows    = []
   errors  = []

   if obj.respond_to? :to_a    ### convert activerecord relation to array (of records)
     recs = obj.to_a
   elsif obj.is_a? Array
     recs = obj
   else
     ## return as is; cannot convert
     ##   todo/fix: handle cannot convert different (e.g. except etc.) - why? why not??
     puts "!!!! [as_tabular] sorry; can't convert <#{obj.class.name}> - Array or to_a method required"
     return obj
   end


     recs.each do |rec|
       puts "rec #{rec.class.name}"
       if rec.respond_to? :as_row
         row = rec.as_row
         rows << row.values   ## add rows as is 1:1
       elsif rec.respond_to?( :as_json_v3 ) ||
             rec.respond_to?( :as_json_v2 ) ||
             rec.respond_to?( :as_json )    ||
             rec.is_a?( Hash )   ## allow (plain) hash too  - give it priority (try first?) - why? why not??

         if rec.respond_to? :as_json_v3
             row = rec.as_json_v3
         elsif rec.respond_to? :as_json_v2
             row = rec.as_json_v2
         elsif rec.respond_to? :as_json
             row = rec.as_json
         else
             row = rec    ## assume it's already a hash (with key/value pairs)
         end

         ##  convert nested values e.g. array and hash to strings
         values = row.values.map do |value|
           if value.is_a? Hash
             ## todo: use our own "pretty printer" e.g. use unqouted strings - why? why not?
             value.to_json  ## use to_json "key": "value" instead of :key => "value"
           elsif value.is_a? Array
             ## todo: use our own "pretty printer" e.g. use unqouted strings - why? why not?
             ## value = "[#{value.join('|')}]" ## use | for joins (instead of ,) - why? why not?? keep comma(,) - why? why not??
             value.to_json
           else
             value
           end
         end
         pp values
         rows << values
       else
          ## todo: add record index - why? why not?
          puts "sorry; can't convert - as_row or as_json method or hash required"
          errors << "sorry; can't convert <#{rec.class.name}> - as_row or as_json method or hash required"
          next
       end

       ## check headers - always must match!!!!!!!
       if headers.empty?
         headers_clone = row.keys
         pp headers_clone
         headers = headers_clone.map { |header| header.to_s }
         pp headers
       else
         ## todo: check if headers match!!!
       end
     end  # recs.each

  if errors.empty?
    Tabular.new( headers, rows )
  else   ## return row of errors
    ##  return errors as a (simple) multi-line string - why? why not??
    errors.join( "\n" )
  end

end

#content_type(type = nil) ⇒ Object

delegate some helpers too



23
# File 'lib/webservice/base/response_handler.rb', line 23

def content_type( type=nil )  @app.content_type( type ); end

#envObject



20
# File 'lib/webservice/base/response_handler.rb', line 20

def env()       @app.env;       end

#handle_response(obj, opts = {}) ⇒ Object

todo: add as_json like opts={} why? why not?



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/webservice/base/response_handler.rb', line 28

def handle_response( obj, opts={} )
  puts "[Webservice::Handler#handle_response (#{request.path_info}) params: #{params.inspect}] - obj : #{obj.class.name}"
  pp obj

  ## "magic" param format; default to json
  format = params['format'] || 'json'

  ## note: response.body must be (expects) an array!!!
  ##   thus, [json] etc.

  if format == 'csv'  || format == 'txt' ||
     format == 'html' || format == 'htm'

    data = as_tabular( obj )

    if data.is_a? Tabular
      if format == 'csv'  || format == 'txt'
         content_type :txt   ## use csv content type - why? why not??
         response.body = [data.to_csv]
      else
        ## assume html
        content_type :html
        response.body = [data.to_html_table]
      end
    else
      ## wrong format (expected Tabular from as_tabular - cannot convert)
      ##   todo: issue warning/notice about wrong format - how?
      ##   use different http status code - why? why not??
      content_type :txt
      ##  todo/check: use just data.to_s  for all - why? why not?
      ## for now return as is (convert to string with to_s or inspect)
      response.body = [data.is_a?( String ) ? data.to_s : data.inspect]
    end
  else    ## default/assume json
    data = as_json( obj )

    ## note: hash or array required!!! for now for json generation
    #   hash   => single record
    #   array  => multiple records (that is, array of hashes)

    if data.is_a?( Hash ) || data.is_a?( Array )
      json = JSON.pretty_generate( data )   ## use pretty printer

      callback = params.delete( 'callback' )

      if callback
        content_type :js
        response.body = ["#{callback}(#{json})"]
      else
        content_type :json
        response.body = [json]
      end
    else
       ## todo/fix/check: change http status to unprocessable entity
       ##   or something --  why ??? why not??
       ##
       ##  allow "standalone" number, nils, strings - why? why not?
       ##   for now valid json must be wrapped in array [] or hash {}
       content_type :txt
       ##  todo/check: use just data.to_s  for all - why? why not?
       ## for now return as is (convert to string with to_s or inspect)
       response.body = [data.is_a?( String ) ? data.to_s : data.inspect]
    end
  end
end

#paramsObject



19
# File 'lib/webservice/base/response_handler.rb', line 19

def params()    @app.params;    end

#requestObject

delegate request, response, params, env

todo/fix: use def_delegate - why? why not???


17
# File 'lib/webservice/base/response_handler.rb', line 17

def request()   @app.request;   end

#responseObject



18
# File 'lib/webservice/base/response_handler.rb', line 18

def response()  @app.response;  end