Class: DataAPI

Inherits:
ActiveRecord::Base
  • Object
show all
Defined in:
app/models/data_api.rb

Defined Under Namespace

Modules: DataModels Classes: APIData, DataModel, DatabaseMaintainer, Request, Schema

Constant Summary collapse

OWNER_PRIMARY_KEYS =
%w(id uuid email uid)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#exceptionObject

Returns the value of attribute exception


2
3
4
# File 'app/models/data_api.rb', line 2

def exception
  @exception
end

#specified_resource_idObject Also known as: specified_resource_ids

Returns the value of attribute specified_resource_id


2
3
4
# File 'app/models/data_api.rb', line 2

def specified_resource_id
  @specified_resource_id
end

Class Method Details

.database_urlObject

Get the System API Database URL


43
44
45
46
47
48
49
50
51
52
53
54
# File 'app/models/data_api.rb', line 43

def self.database_url
  return @database_url if @database_url.present?
  if Rails.env.test?
    @database_url = "sqlite3:db/test_api.sqlite3"
  elsif ENV['API_DATABASE_URL'].blank?
    possible_databases = ENV.select { |k| k.match(/(SQL|DATABASE)_.*URL/) }.map { |_, v| v }
    possible_databases.delete(ENV['DATABASE_URL'])
    @database_url = possible_databases.first || ENV['DATABASE_URL']
  else
    @database_url = ENV['API_DATABASE_URL']
  end
end

.find_by_path(path, include_not_public: false, include_inaccessible: false) ⇒ Object

Find a DataAPI by a resource path TODO: cache the result


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
# File 'app/models/data_api.rb', line 58

def self.find_by_path(path, include_not_public: false, include_inaccessible: false)
  # scope the collection
  if include_inaccessible
    scoped_collection = DataAPI.all
  else
    scoped_collection = DataAPI.where(accessible: true)
  end

  unless include_not_public
    scoped_collection = scoped_collection.where(public: true)
  end

  # if the resource path might be a specified resource path
  possible_specified_resource_path = path.match(%r{(?<path>.+)\/(?<id>[^\/]+)\z})

  # query the database to find the result
  if possible_specified_resource_path
    data_api = scoped_collection.find_by(
      path: [path, possible_specified_resource_path[:path]]
    )
    data_api.specified_resource_id = possible_specified_resource_path[:id] if \
      data_api.present? && data_api.path != path
  else
    data_api = scoped_collection.find_by(path: path)
  end

  data_api
end

Instance Method Details

#columnsObject

List of columns


101
102
103
104
# File 'app/models/data_api.rb', line 101

def columns
  return @columns if @columns
  @columns = schema.keys.map(&:to_sym)
end

#data_api_api_dataObject

Returns all the API data


157
158
159
# File 'app/models/data_api.rb', line 157

def data_api_api_data
  data_model.all
end

#data_countObject


184
185
186
# File 'app/models/data_api.rb', line 184

def data_count
  data_model.count
end

#data_modelObject

Get the data model of this API Data


169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'app/models/data_api.rb', line 169

def data_model
  return DataModels.get(name.classify) if DataModels.has?(name.classify)

  DataModels.construct(name.classify,
    database_url: get_database_url,
    table_name: table_name,
    primary_key: primary_key,
    organization_code: organization_code,
    owned_by_user: owned_by_user,
    owner_primary_key: owner_primary_key,
    owner_foreign_key: owner_foreign_key,
    updated_at: updated_at
  )
end

#fieldsObject

List of accessible fields


107
108
109
110
111
112
113
114
# File 'app/models/data_api.rb', line 107

def fields
  return @fields if @fields
  @fields = columns
  @fields << :id
  @fields &= data_model.columns.map { |c| c.name.to_sym }
  @fields << :owner if owner?
  @fields
end

#get_database_urlObject

Get the database URL of this data API (prefixed with 'get' to separate with the original database_url getter,

which returns nil if the outer database_url for this API is not setted)

164
165
166
# File 'app/models/data_api.rb', line 164

def get_database_url
  self[:database_url].present? ? self[:database_url] : DataAPI.database_url
end

#includable_fieldsObject

List of accessible fields


139
140
141
142
143
144
# File 'app/models/data_api.rb', line 139

def includable_fields
  return @includable_fields if @includable_fields
  @includable_fields = []
  @includable_fields << :owner if owner?
  @includable_fields
end

#initialize_management_api_keyObject


207
208
209
210
# File 'app/models/data_api.rb', line 207

def initialize_management_api_key
  return if management_api_key.present?
  self.management_api_key = SecureRandom.urlsafe_base64(64).gsub(/[^a-zA-Z0-9]/, '0')
end

#nilify_blanksObject


212
213
214
215
216
217
218
219
# File 'app/models/data_api.rb', line 212

def nilify_blanks
  self.organization_code = nil if organization_code.blank?
  self.description = nil if description.blank?
  self.notes = nil if notes.blank?
  self.database_url = nil if database_url.blank?
  self.owner_primary_key = nil if owner_primary_key.blank?
  self.owner_foreign_key = nil if owner_foreign_key.blank?
end

#owner?Boolean

Is this API's data owned by users?

Returns:


96
97
98
# File 'app/models/data_api.rb', line 96

def owner?
  owned_by_user
end

#owner_write_permitted_fields(primary_key: true) ⇒ Object


126
127
128
129
130
131
132
133
134
135
136
# File 'app/models/data_api.rb', line 126

def owner_write_permitted_fields(primary_key: true)
  if primary_key
    return @owner_write_permitted_fields if @owner_write_permitted_fields
    @owner_write_permitted_fields = writable_fields(primary_key: true)
    @owner_write_permitted_fields -= [owner_foreign_key]
  else
    return @owner_write_permitted_fields_without_primary_key if @owner_write_permitted_fields_without_primary_key
    @owner_write_permitted_fields_without_primary_key = writable_fields(primary_key: false)
    @owner_write_permitted_fields_without_primary_key -= [owner_foreign_key]
  end
end

#reset_data_modelObject


193
194
195
196
197
198
199
200
201
# File 'app/models/data_api.rb', line 193

def reset_data_model
  DataModels.remove_if_exists(name.classify)
  begin
    data_model.connection.schema_cache.clear!
    data_model.reset_column_information
  rescue ActiveRecord::ActiveRecordError => e
    Rails.logger.error e
  end
end

#reset_data_model_if_neededObject


203
204
205
# File 'app/models/data_api.rb', line 203

def reset_data_model_if_needed
  reset_data_model if data_model.try(:updated_at) != updated_at
end

#save_schemaObject


188
189
190
191
# File 'app/models/data_api.rb', line 188

def save_schema
  schema.validate!
  self[:schema] = schema.to_s
end

#schemaObject


87
88
89
# File 'app/models/data_api.rb', line 87

def schema
  @schema ||= DataAPI::Schema.new(self[:schema], true)
end

#schema=(s) ⇒ Object


91
92
93
# File 'app/models/data_api.rb', line 91

def schema=(s)
  @schema = DataAPI::Schema.new(s)
end

#test_updateObject


221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'app/models/data_api.rb', line 221

def test_update
  db_maintainer = DatabaseMaintainer.new(data_model)

  previous_version = DataAPI.find(id)
  return nil if previous_version.blank?

  old_table_name = previous_version.table_name
  new_table_name = table_name
  old_schema = previous_version.schema
  new_schema = schema

  db_maintainer.update_table(old_table_name, new_table_name, old_schema, new_schema, test_run: true)
end

#using_outer_database?Boolean

Is this API using an outer database?

Returns:


152
153
154
# File 'app/models/data_api.rb', line 152

def using_outer_database?
  self[:database_url].present?
end

#using_system_database?Boolean

Is this API using the system database?

Returns:


147
148
149
# File 'app/models/data_api.rb', line 147

def using_system_database?
  self[:database_url].blank?
end

#writable_fields(primary_key: true) ⇒ Object


116
117
118
119
120
121
122
123
124
# File 'app/models/data_api.rb', line 116

def writable_fields(primary_key: true)
  if primary_key
    return @writable_fields if @writable_fields
    @writable_fields = schema.keys
  else
    return @writable_fields_without_primary_key if @writable_fields_without_primary_key
    @writable_fields_without_primary_key = schema.keys - [self.primary_key]
  end
end