Module: MotionModel::Model::PublicClassMethods
- Defined in:
- lib/motion_model/model/model.rb,
lib/motion_model/model/persistence.rb
Instance Method Summary collapse
-
#all ⇒ Object
Returns query result as an array.
-
#belongs_to(relation) ⇒ Object
Use at class level, as follows.
-
#bulk_update(&block) ⇒ Object
Use to do bulk insertion, updating, or deleting without making repeated calls to a delegate.
-
#column?(column) ⇒ Boolean
Returns true if a column exists on this model, otherwise false.
-
#columns(*fields) ⇒ Object
Macro to define names and types of columns.
-
#create(options = {}) ⇒ Object
Creates an object and saves it.
-
#default(column) ⇒ Object
returns default value for this column or nil.
-
#delete_all ⇒ Object
Deletes all rows in the model – no hooks are called and deletes are not cascading so this does not affected related data.
-
#deserialize_from_file(file_name = nil) ⇒ Object
Returns the unarchived object if successful, otherwise false.
-
#destroy_all ⇒ Object
Destroys all rows in the model – before_delete and after_delete hooks are called and deletes are not cascading if declared with :delete => destroy in the has_many macro.
- #documents_file(file_name) ⇒ Object
- #each(&block) ⇒ Object
- #empty? ⇒ Boolean
-
#find(*args, &block) ⇒ Object
(also: #where)
Finds row(s) within the data store.
-
#first ⇒ Object
Retrieves first row of query.
- #generate_belongs_to_id(relation) ⇒ Object
-
#has_many(relation, options = {}) ⇒ Object
Use at class level, as follows:.
-
#last ⇒ Object
Retrieves last row of query.
- #length ⇒ Object (also: #count)
- #order(field_name = nil, &block) ⇒ Object
-
#serialize_to_file(file_name = nil) ⇒ Object
Serializes data to a persistent store (file, in this terminology).
-
#type(column) ⇒ Object
Returns type of this column.
Instance Method Details
#all ⇒ Object
Returns query result as an array
236 237 238 |
# File 'lib/motion_model/model/model.rb', line 236 def all @collection end |
#belongs_to(relation) ⇒ Object
Use at class level, as follows
class Assignee
include MotionModel::Model
columns :assignee_name, :department
belongs_to :task
Allows code like this:
Assignee.find(:assignee_name).like('smith').first.task
138 139 140 141 |
# File 'lib/motion_model/model/model.rb', line 138 def belongs_to(relation) add_field relation, :belongs_to add_field generate_belongs_to_id(relation), :belongs_to_id # a relation is singular. end |
#bulk_update(&block) ⇒ Object
Use to do bulk insertion, updating, or deleting without making repeated calls to a delegate. E.g., when syncing with an external data source.
60 61 62 63 64 |
# File 'lib/motion_model/model/model.rb', line 60 def bulk_update(&block) @_issue_notifications = false class_eval &block @_issue_notifications = true end |
#column?(column) ⇒ Boolean
Returns true if a column exists on this model, otherwise false.
144 145 146 |
# File 'lib/motion_model/model/model.rb', line 144 def column?(column) respond_to?(column) end |
#columns(*fields) ⇒ Object
Macro to define names and types of columns. It can be used in one of two forms:
Pass a hash, and you define columns with types. E.g.,
columns :name => :string, :age => :integer
Pass a hash of hashes and you can specify defaults such as:
columns :name => {:type => :string, :default => 'Joe Bob'}, :age => :integer
Pass an array, and you create column names, all of which have type :string
.
columns :name, :age, :hobby
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/motion_model/model/model.rb', line 81 def columns(*fields) return @_columns.map{|c| c.name} if fields.empty? case fields.first when Hash column_from_hash fields when String, Symbol column_from_string_or_sym fields else raise ArgumentError.new("arguments to `columns' must be a symbol, a hash, or a hash of hashes -- was #{fields.first}.") end unless self.respond_to?(:id) add_field(:id, :integer) end end |
#create(options = {}) ⇒ Object
Creates an object and saves it. E.g.:
@bob = Person.create(:name => 'Bob', :hobby => 'Bird Watching')
returns the object created or false.
163 164 165 166 167 |
# File 'lib/motion_model/model/model.rb', line 163 def create( = {}) row = self.new() row.save row end |
#default(column) ⇒ Object
returns default value for this column or nil.
154 155 156 |
# File 'lib/motion_model/model/model.rb', line 154 def default(column) column_named(column).default || nil end |
#delete_all ⇒ Object
Deletes all rows in the model – no hooks are called and deletes are not cascading so this does not affected related data.
177 178 179 180 181 182 183 184 185 186 |
# File 'lib/motion_model/model/model.rb', line 177 def delete_all # Do each delete so any on_delete and # cascades are called, then empty the # collection and compact the array. bulk_update do @collection.each{|item| item.delete} end @collection = [] @_next_id = 1 end |
#deserialize_from_file(file_name = nil) ⇒ Object
Returns the unarchived object if successful, otherwise false
Note that subsequent calls to serialize/deserialize methods will remember the file name, so they may omit that argument.
Raises a MotionModel::PersistFileFailureError
on failure.
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/motion_model/model/persistence.rb', line 12 def deserialize_from_file(file_name = nil) @file_name = file_name if file_name if File.exist? documents_file(@file_name) error_ptr = Pointer.new(:object) data = NSData.dataWithContentsOfFile(documents_file(@file_name), options:NSDataReadingMappedIfSafe, error:error_ptr) if data.nil? error = error_ptr[0] raise MotionModel::PersistFileFailureError.new "Error when reading the data: #{error}" else bulk_update do collection = NSKeyedUnarchiver.unarchiveObjectWithData(data) end return self end else return false end end |
#destroy_all ⇒ Object
Destroys all rows in the model – before_delete and after_delete hooks are called and deletes are not cascading if declared with :delete => destroy in the has_many macro.
191 192 193 194 195 196 197 198 199 |
# File 'lib/motion_model/model/model.rb', line 191 def destroy_all ids = self.all.map{|item| item.id} bulk_update do ids.each do |item| find(item).destroy end end # Note collection is not emptied, and next_id is not reset. end |
#documents_file(file_name) ⇒ Object
57 58 59 60 |
# File 'lib/motion_model/model/persistence.rb', line 57 def documents_file(file_name) file_path = File.join NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true), file_name file_path end |
#each(&block) ⇒ Object
244 245 246 247 |
# File 'lib/motion_model/model/model.rb', line 244 def each(&block) raise ArgumentError.new("each requires a block") unless block_given? @collection.each{|item| yield item} end |
#empty? ⇒ Boolean
249 250 251 |
# File 'lib/motion_model/model/model.rb', line 249 def empty? @collection.empty? end |
#find(*args, &block) ⇒ Object Also known as: where
Finds row(s) within the data store. E.g.,
@post = Post.find(1) # find a specific row by ID
or…
@posts = Post.find(:author).eq('bob').all
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/motion_model/model/model.rb', line 208 def find(*args, &block) if block_given? matches = @collection.collect do |item| item if yield(item) end.compact return FinderQuery.new(matches) end unless args[0].is_a?(Symbol) || args[0].is_a?(String) target_id = args[0].to_i return @collection.select{|element| element.id == target_id}.first end FinderQuery.new(args[0].to_sym, @collection) end |
#first ⇒ Object
Retrieves first row of query
226 227 228 |
# File 'lib/motion_model/model/model.rb', line 226 def first @collection.first end |
#generate_belongs_to_id(relation) ⇒ Object
123 124 125 |
# File 'lib/motion_model/model/model.rb', line 123 def generate_belongs_to_id(relation) (relation.to_s.singularize.underscore + '_id').to_sym end |
#has_many(relation, options = {}) ⇒ Object
Use at class level, as follows:
class Task
include MotionModel::Model
columns :name, :details, :assignees
has_many :assignees
Note that :assignees must be declared as a virtual attribute on the model before you can has_many on it.
This enables code like:
Task.find(:due_date).gt(Time.now).first.assignees
to get the people assigned to first task that is due after right now.
This must be used with a belongs_to macro in the related model class if you want to be able to access the inverse relation.
118 119 120 121 |
# File 'lib/motion_model/model/model.rb', line 118 def has_many(relation, = {}) raise ArgumentError.new("arguments to has_many must be a symbol or string.") unless [Symbol, String].include? relation.class add_field relation, :has_many, # Relation must be plural end |
#last ⇒ Object
Retrieves last row of query
231 232 233 |
# File 'lib/motion_model/model/model.rb', line 231 def last @collection.last end |
#length ⇒ Object Also known as: count
169 170 171 |
# File 'lib/motion_model/model/model.rb', line 169 def length @collection.length end |
#order(field_name = nil, &block) ⇒ Object
240 241 242 |
# File 'lib/motion_model/model/model.rb', line 240 def order(field_name = nil, &block) FinderQuery.new(@collection).order(field_name, &block) end |
#serialize_to_file(file_name = nil) ⇒ Object
Serializes data to a persistent store (file, in this terminology). Serialization is synchronous, so this will pause your run loop until complete.
file_name
is the name of the persistent store you want to use. If you omit this, it will use the last remembered file name.
Raises a MotionModel::PersistFileError
on failure.
42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/motion_model/model/persistence.rb', line 42 def serialize_to_file(file_name = nil) @file_name = file_name if file_name error_ptr = Pointer.new(:object) data = NSKeyedArchiver.archivedDataWithRootObject @collection unless data.writeToFile(documents_file(@file_name), options: NSDataWritingAtomic, error: error_ptr) # De-reference the pointer. error = error_ptr[0] # Now we can use the `error' object. raise MotionModel::PersistFileError.new "Error when writing data: #{error}" end end |
#type(column) ⇒ Object
Returns type of this column.
149 150 151 |
# File 'lib/motion_model/model/model.rb', line 149 def type(column) column_named(column).type || nil end |