Class: KnuVerse::Knufactor::Resource
- Inherits:
-
Object
- Object
- KnuVerse::Knufactor::Resource
- Extended by:
- Helpers::ResourceClass
- Includes:
- Comparable, Helpers::Resource, Validations::Resource
- Defined in:
- lib/knuverse/knufactor/resource.rb
Overview
A generic API resource TODO: Thread safety
Direct Known Subclasses
Instance Attribute Summary collapse
-
#client ⇒ Object
Returns the value of attribute client.
-
#errors ⇒ Object
readonly
Returns the value of attribute errors.
Class Method Summary collapse
- .all(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?.
-
.path(kind, uri) ⇒ Object
Set the URI path for a resource method.
- .path_for(kind) ⇒ Object
-
.paths ⇒ Hash{Symbol => String}
Create or set a class-level location to store URI paths for methods.
-
.property(name, options = {}) ⇒ Object
Define a property for a model.
- .where(attribute, value, options = {}) ⇒ Object
Instance Method Summary collapse
- #destroy ⇒ Object
-
#initialize(options = {}) ⇒ Resource
constructor
A new instance of Resource.
- #reload ⇒ Object
- #save ⇒ 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, #fresh?, #id, #id_property, #immutable?, #model_name, #new?, #path_for, #paths, #persisted?, #properties, #tainted?, #to_key, #to_model, #to_param, #update
Methods included from Validations::Resource
#validate_id, #validate_mutability
Constructor Details
#initialize(options = {}) ⇒ Resource
Returns a new instance of Resource.
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/knuverse/knufactor/resource.rb', line 149 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
#client ⇒ Object
Returns the value of attribute client.
6 7 8 |
# File 'lib/knuverse/knufactor/resource.rb', line 6 def client @client end |
#errors ⇒ Object (readonly)
Returns the value of attribute errors.
7 8 9 |
# File 'lib/knuverse/knufactor/resource.rb', line 7 def errors @errors end |
Class Method Details
.all(options = {}) ⇒ Object
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/knuverse/knufactor/resource.rb', line 101 def self.all( = {}) # TODO: Add validations for options # TODO: add validation checks for the required pieces raise Exceptions::MissingPath unless path_for(:all) api_client = [:api_client] || APIClient.instance root = name.split('::').last.en.plural.to_underscore # TODO: do something with lazy requests... ResourceCollection.new( api_client.get(path_for(:all))[root].collect do |record| new( entity: record, lazy: ([:lazy] ? true : false), tainted: false, api_client: api_client ) end, type: self, api_client: api_client ) end |
.gen_getter_method(name, opts) ⇒ Object
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/knuverse/knufactor/resource.rb', line 57 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) # Casting values based on type case opts[:type] when :time if @entity[name_as_string] && !@entity[name_as_string].to_s.empty? Time.parse(@entity[name_as_string].to_s).utc end else @entity[name_as_string] end end end end |
.gen_property_methods ⇒ Object
90 91 92 93 94 95 96 97 98 99 |
# File 'lib/knuverse/knufactor/resource.rb', line 90 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
76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/knuverse/knufactor/resource.rb', line 76 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] raise Exceptions::InvalidArguments unless send("validate_#{name}".to_sym, value) end @entity[name.to_s] = opts[:type] == :time ? Time.parse(value.to_s).utc : value @tainted = true @modified_properties << name.to_sym end end end |
.get(id, options = {}) ⇒ Object
126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/knuverse/knufactor/resource.rb', line 126 def self.get(id, = {}) # TODO: Add validations for options raise Exceptions::MissingPath unless path_for(:all) api_client = [:api_client] || APIClient.instance new( entity: api_client.get("#{path_for(:all)}/#{id}"), lazy: false, tainted: false, api_client: api_client ) end |
.immutable(status) ⇒ Object
Can this type of resource be changed client-side?
15 16 17 18 19 20 |
# File 'lib/knuverse/knufactor/resource.rb', line 15 def self.immutable(status) unless status.is_a?(TrueClass) || status.is_a?(FalseClass) raise Exceptions::InvalidArguments end @immutable = status end |
.path(kind, uri) ⇒ Object
Set the URI path for a resource method
42 43 44 |
# File 'lib/knuverse/knufactor/resource.rb', line 42 def self.path(kind, uri) paths[kind.to_sym] = uri end |
.path_for(kind) ⇒ Object
52 53 54 55 |
# File 'lib/knuverse/knufactor/resource.rb', line 52 def self.path_for(kind) guess = kind.to_sym == :all ? route_key : "#{route_key}/#{kind}" paths[kind.to_sym] || guess end |
.paths ⇒ Hash{Symbol => String}
Create or set a class-level location to store URI paths for methods
48 49 50 |
# File 'lib/knuverse/knufactor/resource.rb', line 48 def self.paths @paths ||= {} 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 |
# File 'lib/knuverse/knufactor/resource.rb', line 26 def self.property(name, = {}) @properties ||= {} invalid_prop_names = [ :>, :<, :'=', :class, :def, :%, :'!', :/, :'.', :'?', :*, :'{}', :'[]' ] raise(Exceptions::InvalidProperty) if invalid_prop_names.include?(name.to_sym) @properties[name.to_sym] = end |
.where(attribute, value, options = {}) ⇒ Object
140 141 142 143 144 145 146 147 |
# File 'lib/knuverse/knufactor/resource.rb', line 140 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
#destroy ⇒ Object
174 175 176 177 178 179 180 181 182 183 |
# File 'lib/knuverse/knufactor/resource.rb', line 174 def destroy raise Exceptions::ImmutableModification if immutable? unless new? @api_client.delete("#{path_for(:all)}/#{id}") @lazy = false @tainted = true @entity.delete('id') end true end |
#reload ⇒ Object
185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/knuverse/knufactor/resource.rb', line 185 def reload if new? # Can't reload a new resource false else @entity = @api_client.get("#{path_for(:all)}/#{id}") @lazy = false @tainted = false true end end |
#save ⇒ Object
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/knuverse/knufactor/resource.rb', line 197 def save saveable_data = @entity.select do |prop, value| pr = prop.to_sym go = properties.key?(pr) && !properties[pr][:read_only] && !value.nil? @modified_properties.uniq.include?(pr) if go end if new? @entity = @api_client.post(path_for(:all).to_s, saveable_data) @lazy = true else @api_client.put("#{path_for(:all)}/#{id}", saveable_data) end @tainted = false true end |