Class: SkullIsland::Resource
- Inherits:
-
Object
- Object
- SkullIsland::Resource
- Extended by:
- Helpers::ResourceClass
- Includes:
- Comparable, Helpers::Resource, Validations::Resource
- Defined in:
- lib/skull_island/resource.rb
Overview
A generic API resource TODO: Thread safety
Direct Known Subclasses
SkullIsland::Resources::AccessControlList, SkullIsland::Resources::BasicauthCredential, SkullIsland::Resources::CACertificate, SkullIsland::Resources::Certificate, SkullIsland::Resources::Consumer, SkullIsland::Resources::JWTCredential, SkullIsland::Resources::KeyauthCredential, SkullIsland::Resources::Plugin, SkullIsland::Resources::Route, SkullIsland::Resources::Service, SkullIsland::Resources::Upstream, SkullIsland::Resources::UpstreamTarget
Instance Attribute Summary collapse
-
#api_client ⇒ Object
Returns the value of attribute api_client.
-
#entity ⇒ Object
readonly
Returns the value of attribute entity.
-
#errors ⇒ Object
readonly
Returns the value of attribute errors.
Class Method Summary collapse
- .all(options = {}) ⇒ Object
- .cleanup_except(project, keep_these, from_these = nil) ⇒ Object
-
.find(attribute, value, options = {}) ⇒ Object
Returns the first (and hopefully only) resource given some criteria This is a very crude helper and could be made much better.
- .from_hash(hash, options = {}) ⇒ Object
- .gen_getter_method(name, opts) ⇒ Object
- .gen_property_methods ⇒ Object
- .gen_setter_method(name, opts) ⇒ Object
- .get(id, options = {}) ⇒ Object
-
.immutable(status) ⇒ Object
Can this type of resource be changed client-side?.
-
.property(name, options = {}) ⇒ Object
Define a property for a model.
-
.relative_uri ⇒ Object
The URI (relative to the API base) for this object (or its index/list).
- .where(attribute, value, options = {}) ⇒ Object
Instance Method Summary collapse
-
#initialize(options = {}) ⇒ Resource
constructor
A new instance of Resource.
- #relative_uri ⇒ Object
Methods included from Helpers::ResourceClass
determine_getter_names, determine_setter_names, human, i18n_key, immutable?, param_key, properties, route_key
Methods included from Helpers::Resource
#<=>, #datetime_from_params, #delayed_set, #destroy, #digest, #digest_properties, #find_by_digest, #fresh?, #host_regex, #id, #id_property, #immutable?, #import_update_or_skip, #lookup, #model_name, #new?, #persisted?, #postprocess_created_at, #postprocess_updated_at, #properties, #prune_for_save, #recursive_erubi, #reload, #required_properties, #save, #save_uri, #supports_meta?, #tainted?, #to_param, #to_s, #update
Methods included from Validations::Resource
#validate_id, #validate_mutability, #validate_required_properties, #validate_tags
Constructor Details
#initialize(options = {}) ⇒ Resource
Returns a new instance of Resource.
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/skull_island/resource.rb', line 192 def initialize( = {}) # TODO: better options validations raise Exceptions::InvalidOptions unless .is_a?(Hash) @entity = [:entity] || {} # Allows lazy-loading if we're told this is a lazy instance # This means only the minimal attributes were fetched. # This shouldn't be set by end-users. @lazy = .key?(:lazy) ? [:lazy] : false # This allows local, user-created instances to be differentiated from fetched # instances from the backend API. This shouldn't be set by end-users. @tainted = .key?(:tainted) ? [:tainted] : true # This is the API Client used to get data for this resource @api_client = [:api_client] || APIClient.instance @errors = {} # A place to store which properties have been modified @modified_properties = [] validate_mutability validate_id self.class.class_eval { gen_property_methods } end |
Instance Attribute Details
#api_client ⇒ Object
Returns the value of attribute api_client.
7 8 9 |
# File 'lib/skull_island/resource.rb', line 7 def api_client @api_client end |
#entity ⇒ Object (readonly)
Returns the value of attribute entity.
8 9 10 |
# File 'lib/skull_island/resource.rb', line 8 def entity @entity end |
#errors ⇒ Object (readonly)
Returns the value of attribute errors.
8 9 10 |
# File 'lib/skull_island/resource.rb', line 8 def errors @errors end |
Class Method Details
.all(options = {}) ⇒ Object
92 93 94 95 96 97 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 |
# File 'lib/skull_island/resource.rb', line 92 def self.all( = {}) # TODO: Add validations for options # TODO: add validation checks for the required pieces api_client = [:api_client] || APIClient.instance root = 'data' # root for API JSON response data # TODO: do something with lazy requests... collection_entity = api_client.cache(relative_uri) do |client| client.get(relative_uri)[root] end ResourceCollection.new( collection_entity.collect do |record| unless [:lazy] api_client.invalidate_cache_for "#{relative_uri}/#{record['id']}" api_client.cache("#{relative_uri}/#{record['id']}") do record end end new( entity: record, lazy: ([:lazy] ? true : false), tainted: false, api_client: api_client ) end, type: self, api_client: api_client ) end |
.cleanup_except(project, keep_these, from_these = nil) ⇒ Object
183 184 185 186 187 188 189 190 |
# File 'lib/skull_island/resource.rb', line 183 def self.cleanup_except(project, keep_these, from_these = nil) old_resources = from_these || where(:project, project) old_resources.reject { |res| keep_these.include?(res.id) }.map do |res| puts "[WARN] ! Removing #{name} (#{res.id})" res.destroy end end |
.find(attribute, value, options = {}) ⇒ Object
Returns the first (and hopefully only) resource given some criteria This is a very crude helper and could be made much better
141 142 143 144 145 146 |
# File 'lib/skull_island/resource.rb', line 141 def self.find(attribute, value, = {}) results = where(attribute, value, ) raise Exceptions::AmbiguousFind, 'Found more than one result' if results.size > 1 results.first end |
.from_hash(hash, options = {}) ⇒ Object
125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/skull_island/resource.rb', line 125 def self.from_hash(hash, = {}) # TODO: better options validations raise Exceptions::InvalidOptions unless .is_a?(Hash) api_client = [:api_client] || APIClient.instance new( entity: hash, lazy: true, tainted: true, api_client: api_client ) end |
.gen_getter_method(name, opts) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/skull_island/resource.rb', line 40 def self.gen_getter_method(name, opts) determine_getter_names(name, opts).each do |method_name| define_method(method_name) do name_as_string = name.to_s reload if @lazy && !@entity.key?(name_as_string) if opts[:postprocess] send("postprocess_#{name}".to_sym, @entity[name_as_string]) else @entity[name_as_string] end end end end |
.gen_property_methods ⇒ Object
75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/skull_island/resource.rb', line 75 def self.gen_property_methods properties.each do |prop, opts| # Getter methods next if opts[:id_property] gen_getter_method(prop, opts) unless opts[:write_only] # Setter methods (don't make one for obviously read-only properties) gen_setter_method(prop, opts) unless opts[:read_only] end end |
.gen_setter_method(name, opts) ⇒ Object
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/skull_island/resource.rb', line 55 def self.gen_setter_method(name, opts) determine_setter_names(name, opts).each do |method_name| define_method(method_name) do |value| raise Exceptions::ImmutableModification if immutable? if opts[:validate] && !send("validate_#{name}".to_sym, value) raise Exceptions::InvalidArguments, name end @entity[name.to_s] = if opts[:preprocess] send("preprocess_#{name}".to_sym, value) else value end @tainted = true @modified_properties << name.to_sym end end end |
.get(id, options = {}) ⇒ Object
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 |
# File 'lib/skull_island/resource.rb', line 148 def self.get(id, = {}) # TODO: Add validations for options api_client = [:api_client] || APIClient.instance if [:lazy] new( entity: { 'id' => id }, lazy: true, tainted: false, api_client: api_client ) else entity_data = api_client.cache("#{relative_uri}/#{id}") do |client| client.get("#{relative_uri}/#{id}") end new( entity: entity_data, lazy: false, tainted: false, api_client: api_client ) end end |
.immutable(status) ⇒ Object
Can this type of resource be changed client-side?
16 17 18 19 20 |
# File 'lib/skull_island/resource.rb', line 16 def self.immutable(status) raise Exceptions::InvalidArguments unless status.is_a?(TrueClass) || status.is_a?(FalseClass) @immutable = status end |
.property(name, options = {}) ⇒ Object
add more validations on options and names
Define a property for a model
26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/skull_island/resource.rb', line 26 def self.property(name, = {}) @properties ||= {} invalid_prop_names = %i[ > < = class def % ! / . ? * {} \[\] ] raise(Exceptions::InvalidProperty) if invalid_prop_names.include?(name.to_sym) @properties[name.to_sym] = end |
.relative_uri ⇒ Object
The URI (relative to the API base) for this object (or its index/list)
88 89 90 |
# File 'lib/skull_island/resource.rb', line 88 def self.relative_uri route_key end |
.where(attribute, value, options = {}) ⇒ Object
174 175 176 177 178 179 180 181 |
# File 'lib/skull_island/resource.rb', line 174 def self.where(attribute, value, = {}) # TODO: validate incoming options [:comparison] ||= value.is_a?(Regexp) ? :match : '==' api_client = [:api_client] || APIClient.instance all(lazy: ([:lazy] ? true : false), api_client: api_client).where( attribute, value, comparison: [:comparison] ) end |
Instance Method Details
#relative_uri ⇒ Object
217 218 219 |
# File 'lib/skull_island/resource.rb', line 217 def relative_uri "#{self.class.relative_uri}/#{id}" end |