Class: MontageRails::Base
- Inherits:
-
Object
- Object
- MontageRails::Base
- Extended by:
- ActiveModel::Callbacks, ActiveModel::Naming
- Includes:
- ActiveModel::Model
- Defined in:
- lib/montage_rails/base.rb,
lib/montage_rails/base/column.rb
Defined Under Namespace
Classes: Column
Instance Attribute Summary collapse
-
#persisted ⇒ Object
(also: #persisted?)
readonly
Returns the value of attribute persisted.
Class Method Summary collapse
-
.all ⇒ Object
Fetch all the documents.
- .attributes_from_response(response) ⇒ Object
-
.belongs_to(table) ⇒ Object
Define a belongs_to relationship.
-
.cache ⇒ Object
Define a new instance of the query cache.
-
.column_names ⇒ Object
Returns an array of the column names for the table.
-
.columns ⇒ Object
Returns an array of MontageRails::Base::Column’s for the schema.
-
.create(params = {}) ⇒ Object
Initialize and save a new instance of the object.
-
.find_by_id(value) ⇒ Object
(also: find)
Find a record by the id.
-
.find_or_initialize_by(params = {}) ⇒ Object
Find the record using the given params, or initialize a new one with those params.
-
.has_many(table, options = {}) ⇒ Object
Define a has_many relationship.
-
.inspect ⇒ Object
Returns a string like ‘Post id:integer, title:string, body:text’.
-
.logger ⇒ Object
Hook into the Rails logger.
- .method_missing(method_name, *args, &block) ⇒ Object
-
.relation ⇒ Object
Setup a class level instance of the MontageRails::Relation object.
- .respond_to_missing?(method_name, include_private = false) ⇒ Boolean
-
.set_table_name(value) ⇒ Object
(also: table_name=)
Redefine the table name.
-
.table_name ⇒ Object
The pluralized table name used in API requests.
Instance Method Summary collapse
- #==(other) ⇒ Object
-
#attribute_for_inspect(attr_name) ⇒ Object
Returns an
#inspect-like string for the value of the attributeattr_name. -
#attributes_valid? ⇒ Boolean
Performs a check to ensure that required columns have a value.
-
#column_for(name) ⇒ Object
Returns the Column class instance for the attribute passed in.
-
#destroy ⇒ Object
Destroy the copy of this record from the database.
-
#dirty? ⇒ Boolean
Checks if the attributes have changed, and returns true if they are “dirty”.
-
#initialize(params = {}) ⇒ Base
constructor
A new instance of Base.
-
#inspect ⇒ Object
Returns the contents of the record as a nicely formatted string.
- #new_record? ⇒ Boolean
-
#payload ⇒ Object
Required for notifications to work, returns a payload suitable for the log subscriber.
-
#reload ⇒ Object
Reload the current document.
-
#save ⇒ Object
Save the record to the database.
-
#save! ⇒ Object
The bang method for save, which will raise an exception if saving is not successful.
-
#update_attributes(params) ⇒ Object
Update the given attributes for the document.
-
#updateable_attributes(include_id = false) ⇒ Object
The attributes used to update the document.
Constructor Details
#initialize(params = {}) ⇒ Base
Returns a new instance of Base.
197 198 199 200 201 202 203 204 205 206 |
# File 'lib/montage_rails/base.rb', line 197 def initialize(params = {}) run_callbacks :initialize do initialize_columns @persisted = params[:persisted] ? params[:persisted] : false @current_method = "Load" @errors = ActiveModel::Errors.new(self) super(params) @old_attributes = attributes.clone end end |
Instance Attribute Details
#persisted ⇒ Object (readonly) Also known as: persisted?
Returns the value of attribute persisted.
190 191 192 |
# File 'lib/montage_rails/base.rb', line 190 def persisted @persisted end |
Class Method Details
.all ⇒ Object
Fetch all the documents
123 124 125 |
# File 'lib/montage_rails/base.rb', line 123 def all relation.to_a end |
.attributes_from_response(response) ⇒ Object
179 180 181 182 183 184 185 186 187 |
# File 'lib/montage_rails/base.rb', line 179 def attributes_from_response(response) case response.members when Montage::Documents then response.documents.first.attributes.merge(persisted: true) when Montage::Document then response.document.attributes.merge(persisted: true) when Montage::Errors then raise MontageAPIError, "There was an error with the Montage API: #{response.errors.attributes}" when Montage::Error then raise MontageAPIError, "There was an error with the Montage API: #{response.error.attributes}" else raise MontageAPIError, "There was an error with the Montage API, please try again." end end |
.belongs_to(table) ⇒ Object
Define a belongs_to relationship
66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/montage_rails/base.rb', line 66 def belongs_to(table) class_eval do define_method(table.to_s.tableize.singularize.to_sym) do table.to_s.classify.constantize.find_by_id(__send__(table.to_s.foreign_key)) end define_method("#{table.to_s.tableize.singularize}=") do |record| self.__send__("#{table.to_s.foreign_key}=", record.id) self end end end |
.cache ⇒ Object
Define a new instance of the query cache
29 30 31 |
# File 'lib/montage_rails/base.rb', line 29 def cache @cache ||= QueryCache.new(MontageRails.no_caching) end |
.column_names ⇒ Object
Returns an array of the column names for the table
144 145 146 |
# File 'lib/montage_rails/base.rb', line 144 def column_names columns.map { |c| c.name } end |
.columns ⇒ Object
Returns an array of MontageRails::Base::Column’s for the schema
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/montage_rails/base.rb', line 99 def columns @columns ||= [].tap do |ary| response = connection.schema(table_name) return [] unless response.schema.respond_to?(:fields) ary << Column.new("id", "text", false) ary << Column.new("created_at", "datetime", false) ary << Column.new("updated_at", "datetime", false) response.schema.fields.each do |field| ary << Column.new(field["name"], field["datatype"], field["required"]) instance_eval do define_singleton_method("find_by_#{field["name"]}") do |value| where("#{field["name"]} = '#{value}'").first end end end end end |
.create(params = {}) ⇒ Object
Initialize and save a new instance of the object
150 151 152 |
# File 'lib/montage_rails/base.rb', line 150 def create(params = {}) new(params).save end |
.find_by_id(value) ⇒ Object Also known as: find
Find a record by the id
129 130 131 |
# File 'lib/montage_rails/base.rb', line 129 def find_by_id(value) relation.where(id: value).first end |
.find_or_initialize_by(params = {}) ⇒ Object
Find the record using the given params, or initialize a new one with those params
137 138 139 140 |
# File 'lib/montage_rails/base.rb', line 137 def find_or_initialize_by(params = {}) return nil if params.empty? relation.where(params).first || new(params) end |
.has_many(table, options = {}) ⇒ Object
Define a has_many relationship
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/montage_rails/base.rb', line 47 def has_many(table, = {}) class_eval do if [:as] define_method(table.to_s.tableize.to_sym) do table.to_s.classify.constantize.where( "#{[:as]}_id".to_sym => id, "#{[:as]}_type".to_sym => self.class.name.demodulize ) end else define_method(table.to_s.tableize.to_sym) do table.to_s.classify.constantize.where("#{self.class.table_name.demodulize.underscore.singularize.foreign_key} = #{id}") end end end end |
.inspect ⇒ Object
Returns a string like ‘Post id:integer, title:string, body:text’
156 157 158 159 160 161 162 163 |
# File 'lib/montage_rails/base.rb', line 156 def inspect if self == Base super else attr_list = columns.map { |c| "#{c.name}: #{c.type}" } * ', ' "#{super}(#{attr_list})" end end |
.logger ⇒ Object
Hook into the Rails logger
35 36 37 |
# File 'lib/montage_rails/base.rb', line 35 def logger @logger ||= Rails.logger end |
.method_missing(method_name, *args, &block) ⇒ Object
165 166 167 168 169 170 171 172 173 |
# File 'lib/montage_rails/base.rb', line 165 def method_missing(method_name, *args, &block) __send__(:columns) if respond_to?(method_name.to_sym) __send__(method_name.to_sym, *args) else super(method_name, *args, &block) end end |
.relation ⇒ Object
Setup a class level instance of the MontageRails::Relation object
41 42 43 |
# File 'lib/montage_rails/base.rb', line 41 def relation @relation = Relation.new(self) end |
.respond_to_missing?(method_name, include_private = false) ⇒ Boolean
175 176 177 |
# File 'lib/montage_rails/base.rb', line 175 def respond_to_missing?(method_name, include_private = false) __send__(:column_names).include?(method_name.to_s.split("_").first) || super(method_name, include_private) end |
.set_table_name(value) ⇒ Object Also known as: table_name=
Redefine the table name
87 88 89 90 91 92 93 |
# File 'lib/montage_rails/base.rb', line 87 def set_table_name(value) instance_eval do define_singleton_method(:table_name) do value end end end |
.table_name ⇒ Object
The pluralized table name used in API requests
81 82 83 |
# File 'lib/montage_rails/base.rb', line 81 def table_name self.name.demodulize.underscore.pluralize end |
Instance Method Details
#==(other) ⇒ Object
208 209 210 |
# File 'lib/montage_rails/base.rb', line 208 def ==(other) attributes == other.attributes end |
#attribute_for_inspect(attr_name) ⇒ Object
Returns an #inspect-like string for the value of the attribute attr_name. String attributes are elided after 50 characters, and Date and Time attributes are returned in the :db format. Other attributes return the value of #inspect without modification.
person = Person.create!(:name => "David Heinemeier Hansson " * 3)
person.attribute_for_inspect(:name)
# => '"David Heinemeier Hansson David Heinemeier Hansson D..."'
person.attribute_for_inspect(:created_at)
# => '"2009-01-12 04:48:57"'
380 381 382 383 384 385 386 387 388 389 390 |
# File 'lib/montage_rails/base.rb', line 380 def attribute_for_inspect(attr_name) value = attributes[attr_name] if value.is_a?(String) && value.length > 50 "#{value[0..50]}...".inspect elsif value.is_a?(Date) || value.is_a?(Time) %("#{value.to_s(:db)}") else value.inspect end end |
#attributes_valid? ⇒ Boolean
Performs a check to ensure that required columns have a value
343 344 345 346 347 348 |
# File 'lib/montage_rails/base.rb', line 343 def attributes_valid? attributes.each do |key, value| next unless column_class = column_for(key.to_s) return false unless column_class.value_valid?(value) end end |
#column_for(name) ⇒ Object
Returns the Column class instance for the attribute passed in
337 338 339 |
# File 'lib/montage_rails/base.rb', line 337 def column_for(name) self.class.columns.select { |column| column.name == name }.first end |
#destroy ⇒ Object
Destroy the copy of this record from the database
309 310 311 312 313 314 315 |
# File 'lib/montage_rails/base.rb', line 309 def destroy @current_method = "Delete" notify(self) { connection.delete_document(self.class.table_name, id) } @persisted = false self end |
#dirty? ⇒ Boolean
Checks if the attributes have changed, and returns true if they are “dirty”
303 304 305 |
# File 'lib/montage_rails/base.rb', line 303 def dirty? @old_attributes != attributes end |
#inspect ⇒ Object
Returns the contents of the record as a nicely formatted string.
394 395 396 397 398 399 400 401 |
# File 'lib/montage_rails/base.rb', line 394 def inspect attributes_as_nice_string = self.class.column_names.collect { |name| if attributes[name.to_sym] || new_record? "#{name}: #{attribute_for_inspect(name.to_sym)}" end }.compact.join(", ") "#<#{self.class} #{attributes_as_nice_string}>" end |
#new_record? ⇒ Boolean
331 332 333 |
# File 'lib/montage_rails/base.rb', line 331 def new_record? !persisted? end |
#payload ⇒ Object
Required for notifications to work, returns a payload suitable for the log subscriber
359 360 361 362 363 364 |
# File 'lib/montage_rails/base.rb', line 359 def payload { reql: reql_payload[@current_method], name: "#{self.class.name} #{@current_method}" } end |
#reload ⇒ Object
Reload the current document
319 320 321 322 323 324 325 326 327 328 329 |
# File 'lib/montage_rails/base.rb', line 319 def reload @current_method = "Load" response = notify(self) do connection.document(self.class.table_name, id) end initialize(attributes_from_response(response)) @persisted = true self end |
#save ⇒ Object
Save the record to the database
Will return false if the attributes are not valid
Upon successful creation or update, will return true, otherwise returns false
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 |
# File 'lib/montage_rails/base.rb', line 218 def save run_callbacks :save do return false unless valid? && attributes_valid? if persisted? @current_method = "Update" if dirty? @response = notify(self) do connection.create_or_update_documents(self.class.table_name, [updateable_attributes(true)]) end initialize(attributes_from_response(@response)) else return initialize(@old_attributes) end else run_callbacks :create do @current_method = "Create" @response = notify(self) do connection.create_or_update_documents(self.class.table_name, [updateable_attributes(false)]) end if @response.success? @persisted = true initialize(attributes_from_response(@response)) else break end end end end @response.success? ? self : false end |
#save! ⇒ Object
The bang method for save, which will raise an exception if saving is not successful
257 258 259 260 261 262 263 264 265 |
# File 'lib/montage_rails/base.rb', line 257 def save! response = save unless response raise MontageAPIError, "There was an error saving your data" end response end |
#update_attributes(params) ⇒ Object
Update the given attributes for the document
Returns false if the given attributes aren’t valid
Returns a copy of self if updating is successful
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 |
# File 'lib/montage_rails/base.rb', line 273 def update_attributes(params) @old_attributes = attributes.clone params.each do |key, value| if respond_to?(key.to_sym) coerced_value = column_for(key.to_s).coerce(value) send("#{key}=", coerced_value) end end return self unless dirty? if valid? && attributes_valid? @current_method = id.nil? ? "Create" : "Update" response = notify(self) do connection.create_or_update_documents(self.class.table_name, [updateable_attributes(!id.nil?)]) end initialize(attributes_from_response(response)) @persisted = true self else initialize(@old_attributes) false end end |
#updateable_attributes(include_id = false) ⇒ Object
The attributes used to update the document
352 353 354 |
# File 'lib/montage_rails/base.rb', line 352 def updateable_attributes(include_id = false) include_id ? attributes.except(:created_at, :updated_at) : attributes.except(:created_at, :updated_at, :id) end |