Class: DhanHQ::BaseModel
- Inherits:
-
Object
- Object
- DhanHQ::BaseModel
- Extended by:
- APIHelper, AttributeHelper, RequestHelper, ResponseHelper, ValidationHelper
- Includes:
- APIHelper, AttributeHelper, RequestHelper, ResponseHelper, ValidationHelper
- Defined in:
- lib/DhanHQ/core/base_model.rb
Overview
Base class for resource objects Handles validation, attribute mapping, and response parsing
Direct Known Subclasses
Models::AlertOrder, Models::Edis, Models::ExpiredOptionsData, Models::ForeverOrder, Models::Funds, Models::HistoricalData, Models::Holding, Models::Instrument, Models::KillSwitch, Models::LedgerEntry, Models::Margin, Models::MarketFeed, Models::OptionChain, Models::Order, Models::OrderUpdate, Models::PnlExit, Models::Position, Models::Postback, Models::Profile, Models::SuperOrder, Models::Trade
Constant Summary
Constants included from ResponseHelper
ResponseHelper::STATUS_ERROR_FALLBACK
Class Attribute Summary collapse
-
.defined_attributes ⇒ Object
readonly
Returns the value of attribute defined_attributes.
Instance Attribute Summary collapse
-
#attributes ⇒ Object
readonly
Attribute Accessors.
-
#errors ⇒ Object
readonly
Attribute Accessors.
Class Method Summary collapse
-
.all ⇒ Array<DhanHQ::BaseModel>, DhanHQ::ErrorObject
Find all resources.
-
.api ⇒ Object
Provide a shared BaseAPI instance for this model.
-
.api_type ⇒ Object
Provide a default API type, can be overridden by child classes.
-
.attributes(*args) ⇒ Object
Registers the set of attributes for this model.
-
.create(attributes) ⇒ DhanHQ::BaseModel, DhanHQ::ErrorObject
Create a new resource.
-
.find(id) ⇒ DhanHQ::BaseModel, DhanHQ::ErrorObject
Find a resource by ID.
-
.parse_collection_response(response) ⇒ Array<BaseModel>
Helper method to parse a collection response into model instances.
-
.resource ⇒ Object
Returns the API resource used by collection methods.
-
.resource_path ⇒ String
Retrieve the resource path for the API.
-
.validate_attributes(attributes) ⇒ Object
Validate attributes before creating a new instance.
-
.validation_contract ⇒ nil
Default class-level validation contract — returns nil (no validation).
-
.where(params) ⇒ Array<BaseModel>, ...
Fetches records filtered by query parameters.
Instance Method Summary collapse
-
#assign_attributes ⇒ Object
Dynamically assign attributes as methods.
-
#delete ⇒ Boolean
Delete the resource.
-
#destroy ⇒ Boolean
Alias for #delete maintained for ActiveModel familiarity.
-
#id ⇒ String, ...
Identifier inferred from the loaded attributes.
-
#initialize(attributes = {}, skip_validation: false) ⇒ BaseModel
constructor
Initialize a new resource object.
- #new_record? ⇒ Boolean
- #optionchain_api? ⇒ Boolean
- #persisted? ⇒ Boolean
-
#save ⇒ DhanHQ::BaseModel, ...
Persists the current resource by delegating to #create or #update.
- #save! ⇒ DhanHQ::BaseModel
-
#to_request_params ⇒ Hash
Format request parameters before sending to API.
-
#update(attributes = {}) ⇒ DhanHQ::BaseModel, DhanHQ::ErrorObject
Update an existing resource.
-
#valid? ⇒ Boolean
Validate attributes using contract.
-
#validation_contract ⇒ nil
Default validation contract — returns nil (no validation).
Methods included from APIHelper
Methods included from AttributeHelper
camelize_keys, inspect, normalize_keys, snake_case, titleize_keys
Methods included from ValidationHelper
Methods included from RequestHelper
Constructor Details
#initialize(attributes = {}, skip_validation: false) ⇒ BaseModel
Initialize a new resource object
30 31 32 33 34 35 36 |
# File 'lib/DhanHQ/core/base_model.rb', line 30 def initialize(attributes = {}, skip_validation: false) @attributes = normalize_keys(attributes) @errors = {} validate! unless skip_validation assign_attributes end |
Class Attribute Details
.defined_attributes ⇒ Object (readonly)
Returns the value of attribute defined_attributes.
41 42 43 |
# File 'lib/DhanHQ/core/base_model.rb', line 41 def defined_attributes @defined_attributes end |
Instance Attribute Details
#attributes ⇒ Object (readonly)
Attribute Accessors
25 26 27 |
# File 'lib/DhanHQ/core/base_model.rb', line 25 def attributes @attributes end |
#errors ⇒ Object (readonly)
Attribute Accessors
25 26 27 |
# File 'lib/DhanHQ/core/base_model.rb', line 25 def errors @errors end |
Class Method Details
.all ⇒ Array<DhanHQ::BaseModel>, DhanHQ::ErrorObject
Find all resources
104 105 106 107 108 |
# File 'lib/DhanHQ/core/base_model.rb', line 104 def all response = resource.get("") parse_collection_response(response) end |
.api ⇒ Object
Provide a shared BaseAPI instance for this model
For child classes, override ‘api_type` or `api` if needed
63 64 65 |
# File 'lib/DhanHQ/core/base_model.rb', line 63 def api @api ||= BaseAPI.new(api_type: api_type) end |
.api_type ⇒ Object
Provide a default API type, can be overridden by child classes
e.g., def self.api_type; :data_api; end
or override the ‘api` method entirely
56 57 58 |
# File 'lib/DhanHQ/core/base_model.rb', line 56 def api_type :order_api end |
.attributes(*args) ⇒ Object
Registers the set of attributes for this model
46 47 48 49 |
# File 'lib/DhanHQ/core/base_model.rb', line 46 def attributes(*args) @defined_attributes ||= [] @defined_attributes.concat(args.map(&:to_s)) end |
.create(attributes) ⇒ DhanHQ::BaseModel, DhanHQ::ErrorObject
Create a new resource
134 135 136 137 138 139 |
# File 'lib/DhanHQ/core/base_model.rb', line 134 def create(attributes) # validate_params!(attributes, validation_contract) response = resource.post("", params: attributes) build_from_response(response) end |
.find(id) ⇒ DhanHQ::BaseModel, DhanHQ::ErrorObject
Find a resource by ID
114 115 116 117 118 119 |
# File 'lib/DhanHQ/core/base_model.rb', line 114 def find(id) response = resource.get("/#{id}") payload = response.is_a?(Array) ? response.first : response build_from_response(payload) end |
.parse_collection_response(response) ⇒ Array<BaseModel>
Helper method to parse a collection response into model instances
145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/DhanHQ/core/base_model.rb', line 145 def parse_collection_response(response) # Some endpoints return arrays, others might return a `[:data]` structure unless response.is_a?(Array) || (response.is_a?(Hash) && response[:data].is_a?(Array)) DhanHQ.logger&.warn( "[DhanHQ::BaseModel] Unexpected response format for collection: #{response.class}. " \ "Expected Array or Hash with :data key." ) return [] end collection = response.is_a?(Array) ? response : response[:data] collection.map { |record| new(record, skip_validation: true) } end |
.resource ⇒ Object
Returns the API resource used by collection methods.
Subclasses may override this to return a specialized API class. By default it simply returns #api.
72 73 74 |
# File 'lib/DhanHQ/core/base_model.rb', line 72 def resource api end |
.resource_path ⇒ String
Retrieve the resource path for the API
79 80 81 |
# File 'lib/DhanHQ/core/base_model.rb', line 79 def resource_path self::HTTP_PATH end |
.validate_attributes(attributes) ⇒ Object
Validate attributes before creating a new instance
92 93 94 95 96 97 |
# File 'lib/DhanHQ/core/base_model.rb', line 92 def validate_attributes(attributes) contract = validation_contract result = contract.call(attributes) raise ArgumentError, "Validation failed: #{result.errors.to_h}" if result.failure? end |
.validation_contract ⇒ nil
Default class-level validation contract — returns nil (no validation). Override in subclasses to provide a contract for class-level validation.
87 88 89 |
# File 'lib/DhanHQ/core/base_model.rb', line 87 def validation_contract nil end |
.where(params) ⇒ Array<BaseModel>, ...
Fetches records filtered by query parameters.
125 126 127 128 |
# File 'lib/DhanHQ/core/base_model.rb', line 125 def where(params) response = resource.get("", params: params) build_from_response(response) end |
Instance Method Details
#assign_attributes ⇒ Object
Dynamically assign attributes as methods
265 266 267 268 269 270 271 |
# File 'lib/DhanHQ/core/base_model.rb', line 265 def assign_attributes self.class.defined_attributes&.each do |attr| instance_variable_set(:"@#{attr}", @attributes[attr]) define_singleton_method(attr) { instance_variable_get(:"@#{attr}") } define_singleton_method(attr.to_s.camelize(:lower)) { instance_variable_get(:"@#{attr}") } end end |
#delete ⇒ Boolean
Delete the resource
Deletes the resource from the remote API.
217 218 219 |
# File 'lib/DhanHQ/core/base_model.rb', line 217 def delete destroy end |
#destroy ⇒ Boolean
Alias for #delete maintained for ActiveModel familiarity.
224 225 226 227 228 229 230 |
# File 'lib/DhanHQ/core/base_model.rb', line 224 def destroy response = self.class.resource.delete("/#{id}") success_response?(response) rescue StandardError => e DhanHQ.logger&.error("[DhanHQ::BaseModel] Error deleting resource #{id}: #{e.class} #{e.}") false end |
#id ⇒ String, ...
Identifier inferred from the loaded attributes.
258 259 260 261 262 |
# File 'lib/DhanHQ/core/base_model.rb', line 258 def id id_value = @attributes[:id] || @attributes[:order_id] || @attributes[:security_id] # Convert to string for consistency, but preserve nil id_value&.to_s end |
#new_record? ⇒ Boolean
236 237 238 |
# File 'lib/DhanHQ/core/base_model.rb', line 236 def new_record? !persisted? end |
#optionchain_api? ⇒ Boolean
273 274 275 |
# File 'lib/DhanHQ/core/base_model.rb', line 273 def optionchain_api? self.class.name.include?("OptionChain") end |
#persisted? ⇒ Boolean
232 233 234 |
# File 'lib/DhanHQ/core/base_model.rb', line 232 def persisted? !!id end |
#save ⇒ DhanHQ::BaseModel, ...
Persists the current resource by delegating to #create or #update.
187 188 189 |
# File 'lib/DhanHQ/core/base_model.rb', line 187 def save new_record? ? self.class.create(attributes) : update(attributes) end |
#save! ⇒ DhanHQ::BaseModel
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/DhanHQ/core/base_model.rb', line 195 def save! result = save return result unless result == false || result.nil? || result.is_a?(DhanHQ::ErrorObject) error_details = if result.is_a?(DhanHQ::ErrorObject) result.errors elsif @errors && !@errors.empty? @errors else "Unknown error" end raise DhanHQ::Error, "Failed to save the record: #{error_details}" end |
#to_request_params ⇒ Hash
Format request parameters before sending to API
Auto-injects dhan_client_id from configuration if not present in attributes and the model requires it (has dhan_client_id as an attribute).
246 247 248 249 250 251 252 253 |
# File 'lib/DhanHQ/core/base_model.rb', line 246 def to_request_params attrs = @attributes.dup # Auto-inject dhan_client_id from configuration if not provided and model supports it if self.class.defined_attributes&.include?("dhan_client_id") && !attrs[:dhan_client_id] && DhanHQ.configuration.client_id attrs[:dhan_client_id] = DhanHQ.configuration.client_id end optionchain_api? ? titleize_keys(attrs) : camelize_keys(attrs) end |
#update(attributes = {}) ⇒ DhanHQ::BaseModel, DhanHQ::ErrorObject
Update an existing resource
174 175 176 177 178 179 180 181 182 |
# File 'lib/DhanHQ/core/base_model.rb', line 174 def update(attributes = {}) response = self.class.resource.put("/#{id}", params: attributes) if success_response?(response) self.class.build_from_response(response) else DhanHQ::ErrorObject.new(response) end end |
#valid? ⇒ Boolean
Validate attributes using contract
278 279 280 281 282 283 284 285 286 287 288 289 290 291 |
# File 'lib/DhanHQ/core/base_model.rb', line 278 def valid? contract_class = validation_contract || self.class.validation_contract return true unless contract_class contract = contract_class.is_a?(Class) ? contract_class.new : contract_class result = contract.call(@attributes) if result.failure? @errors = result.errors.to_h return false end true end |
#validation_contract ⇒ nil
Default validation contract — returns nil (no validation). Models that require instance-level validation must override this method.
166 167 168 |
# File 'lib/DhanHQ/core/base_model.rb', line 166 def validation_contract nil end |