Class: GoogleDataSource::DataSource::Base

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

Overview

Superclass for all data source implementations Offers methods for getting and setting the data and column definitions of the data source

Direct Known Subclasses

CsvData, HtmlData, InvalidData, JsonData, XmlData

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#callbackObject

Callback defines a JavaScript snippet that is appended to the regular data-source reponse. This is currently used to refresh the form in reportings (validation)



10
11
12
# File 'lib/google_data_source/base.rb', line 10

def callback
  @callback
end

#column_labelsObject

Callback defines a JavaScript snippet that is appended to the regular data-source reponse. This is currently used to refresh the form in reportings (validation)



10
11
12
# File 'lib/google_data_source/base.rb', line 10

def column_labels
  @column_labels
end

#errorsObject (readonly)

Define accessors for the data source data, columns and errors



13
14
15
# File 'lib/google_data_source/base.rb', line 13

def errors
  @errors
end

#export_filenameObject

Returns the filename for export without extension. Defaults to “export”



10
11
12
# File 'lib/google_data_source/base.rb', line 10

def export_filename
  @export_filename
end

#formattersObject

Callback defines a JavaScript snippet that is appended to the regular data-source reponse. This is currently used to refresh the form in reportings (validation)



10
11
12
# File 'lib/google_data_source/base.rb', line 10

def formatters
  @formatters
end

#reportingObject

Callback defines a JavaScript snippet that is appended to the regular data-source reponse. This is currently used to refresh the form in reportings (validation)



10
11
12
# File 'lib/google_data_source/base.rb', line 10

def reporting
  @reporting
end

#virtual_columnsObject

Callback defines a JavaScript snippet that is appended to the regular data-source reponse. This is currently used to refresh the form in reportings (validation)



10
11
12
# File 'lib/google_data_source/base.rb', line 10

def virtual_columns
  @virtual_columns
end

#xml_classObject

Callback defines a JavaScript snippet that is appended to the regular data-source reponse. This is currently used to refresh the form in reportings (validation)



10
11
12
# File 'lib/google_data_source/base.rb', line 10

def xml_class
  @xml_class
end

Class Method Details

.from_gdata_params(gdata_params) ⇒ Object

Factory method to create a GDataSource instance from a serie of valid GData parameters, as described in the official documentation (see above links).

gdata_params can be any map-like object that maps keys (like :out, :reqId and so forth) to their values. Keys must be symbols.



107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/google_data_source/base.rb', line 107

def self.from_gdata_params(gdata_params)
  case gdata_params[:out]
  when "json"
    JsonData.new(gdata_params)
  when "html"
    HtmlData.new(gdata_params)
  when "csv"
    CsvData.new(gdata_params)
  when "xml"
    XmlData.new(gdata_params)
  else
    InvalidData.new(gdata_params)
  end
end

.from_params(params) ⇒ Object

Creates a new data source object from the get parameters of the data-source request.



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/google_data_source/base.rb', line 85

def self.from_params(params)
  # Exract GDataSource params from the request.
  gdata_params = {}
  tqx = params[:tqx]
  unless tqx.blank?
    gdata_params[:tqx] = true
    tqx.split(';').each do |kv|
      key, value = kv.split(':')
      gdata_params[key.to_sym] = value
    end
  end

  # Create the appropriate GDataSource instance from the gdata-specific parameters
  gdata_params[:out] ||= "json"    
  gdata = from_gdata_params(gdata_params)
end

Instance Method Details

#[](k) ⇒ Object

Access a GData parameter. k must be symbols, like :out, :reqId.



123
124
125
# File 'lib/google_data_source/base.rb', line 123

def [](k)
  @params[k]
end

#[]=(k, v) ⇒ Object

Sets a GData parameter. k must be symbols, like :out, :reqId. The instance is re-validated afterward.



129
130
131
132
# File 'lib/google_data_source/base.rb', line 129

def []=(k, v)
  @params[k] = v
  validate
end

#add_error(key, message) ⇒ Object

Manually adds a new validation error. key should be a symbol pointing to the invalid parameter or element.



142
143
144
145
# File 'lib/google_data_source/base.rb', line 142

def add_error(key, message)
  @errors[key] = message
  return self
end

#column_idsObject

Returns the ids of the columns



197
198
199
# File 'lib/google_data_source/base.rb', line 197

def column_ids
  columns.collect(&:id)
end

#columnsObject Also known as: cols

Returns the columns in a datasource compatible format Applies all labels set



214
215
216
217
# File 'lib/google_data_source/base.rb', line 214

def columns
  @columns.each { |c| c.label = column_labels.delete(c.id) if column_labels.has_key?(c.id) }
  @columns
end

#columns=(columns) ⇒ Object

Sets the columns which should be sent by the datasource columns is an array of either Hashes with keys (:id, :type, :label) or Column objects



205
206
207
208
209
210
# File 'lib/google_data_source/base.rb', line 205

def columns=(columns)
  @columns = columns.map { |c| c.is_a?(Column) ? c : Column.new(c) }
  @columns.each do |col|
    raise ArgumentError, "Invalid column type: #{col.type}" unless col.valid?
  end
end

#dataObject

Returns the formatted data in the datasource format



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/google_data_source/base.rb', line 168

def data
  @data unless @data.nil?

  # get data from object (eg. Reporting)
  data = @raw_data.respond_to?(:data) ?
    @raw_data.data(:required_columns => required_columns) :
    @raw_data

  # Run formatters and virtual columns
  @data = data.collect do |row|
    row = OpenStruct.new(row) if row.is_a?(Hash)

    column_ids.inject([]) do |columns, column|
      if is_virtual_column?(column)
        columns << virtual_columns[column][:proc].call(row)
      elsif has_formatter?(column)
        columns << {
          :f => formatters[column.to_sym].call(row),
          :v => row.send(column)
        }
      else
        columns << row.send(column)
      end
    end
  end
end

#data=(data) ⇒ Object

Sets the unformatted data of the datasource data is an array either of Hash objects or arbitrary objects

  • Hashes must have keys as column ids

  • Arbitrary object must repond to column id named methods



152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/google_data_source/base.rb', line 152

def data=(data)
  # reset formatted data
  @data     = nil

  # set unformatted data
  @raw_data = data
  validate

  # register virtual columns
  if data.respond_to?(:add_virtual_column)
    @virtual_columns.each { |k, v| data.add_virtual_column(k.to_sym, v[:type]) }
  end
end

#formatObject

Empty method. This is a placeholder implemented by subclasses that return the correct format



276
277
278
# File 'lib/google_data_source/base.rb', line 276

def format
  self[:out]
end

#formatter(column, options = {}, &block) ⇒ Object

Convenience method for formatter definition



41
42
43
44
# File 'lib/google_data_source/base.rb', line 41

def formatter(column, options = {}, &block)
  set_required_columns(column.to_sym, options[:requires]) if options.has_key?(:requires)
  formatters[column.to_sym] = block
end

#guess_columns(data) ⇒ Object

Tries to get a clever column selection from the items collection. Currently only accounts for ActiveRecord objects items is an arbitrary collection of items as passed to the set method



236
237
238
239
240
241
242
243
244
245
246
247
248
249
# File 'lib/google_data_source/base.rb', line 236

def guess_columns(data)
  return data.columns if data.respond_to? :columns

  columns = []
  klass = data.first.class
  klass.columns.each do |column|
    columns << Column.new({
      :id => column.name,
      :label => column.name.humanize,
      :type => 'string' # TODO get the right type
    })
  end
  columns
end

#has_formatter?(column_name) ⇒ Boolean

Returns true if formatter formatter for a certain column is defined

Returns:

  • (Boolean)


36
37
38
# File 'lib/google_data_source/base.rb', line 36

def has_formatter?(column_name)
  @formatters.has_key?(column_name.to_sym)
end

#is_virtual_column?(name) ⇒ Boolean

Return true if virtual column with name exists

Returns:

  • (Boolean)


47
48
49
# File 'lib/google_data_source/base.rb', line 47

def is_virtual_column?(name)
  virtual_columns.has_key?(name)
end

#required_columnsObject

Getter with empty array default



63
64
65
66
# File 'lib/google_data_source/base.rb', line 63

def required_columns
  required = column_ids.inject([]) { |columns, column| columns << @required_columns[column.to_sym] }.flatten.compact
  (required + column_ids).map(&:to_s).uniq
end

#responseObject

Empty method. This is a placeholder implemented by subclasses that produce the response according to a given format.



272
273
# File 'lib/google_data_source/base.rb', line 272

def response
end

#set(data, columns = nil) ⇒ Object

Sets the raw data and the columns simultaniously and tries to guess the columns if not set. data may be an array of rows or an object of a class that support a data(options) and a columns method



228
229
230
231
# File 'lib/google_data_source/base.rb', line 228

def set(data, columns = nil)
  self.data     = data
  self.columns  = columns || guess_columns(@raw_data)
end

#set_required_columns(column, requires = []) ⇒ Object

Add a list of columns to the list of required columns (columns that have to be fetched)



69
70
71
# File 'lib/google_data_source/base.rb', line 69

def set_required_columns(column, requires = [])
  @required_columns[column.to_sym] = requires
end

#valid?Boolean

Checks whether this instance is valid (in terms of configuration parameters) or not.

Returns:

  • (Boolean)


136
137
138
# File 'lib/google_data_source/base.rb', line 136

def valid?
  @errors.size == 0
end

#validateObject

Validates this instance by checking that the configuration parameters conform to the official specs.



253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/google_data_source/base.rb', line 253

def validate
  @errors.clear

  # check validity
  if @raw_data.respond_to?(:valid?) && ! @raw_data.valid?
    add_error(:reqId, "Form validation failed")
  end

  if @params[:tqx]
    add_error(:reqId, "Missing required parameter reqId") unless @params[:reqId]
  
    if @params[:version] && @params[:version] != @version
      add_error(:version, "Unsupported version #{@params[:version]}")
    end
  end
end

#virtual_column(name, options = {}, &block) ⇒ Object

Sets up a virtual column with name and block with is called with a row and returns a string or a hash like “real value”, f: “formatted value”



53
54
55
56
57
58
59
60
# File 'lib/google_data_source/base.rb', line 53

def virtual_column(name, options = {},  &block)
  @raw_data.add_virtual_column(name.to_sym, options[:type] || :string) if @raw_data.respond_to?(:add_virtual_column)
  set_required_columns(name.to_sym, options[:requires]) if options.has_key?(:requires)
  virtual_columns[name.to_sym] = {
    :type => options[:type] || :string,
    :proc => block
  }
end