Module: ModelClass
- Includes:
- OrientSupport::Support
- Included in:
- ActiveOrient::Model
- Defined in:
- lib/model/the_class.rb
Instance Method Summary collapse
- #add_edge_link(name:, direction: :out, edge:) ⇒ Object
-
#all ⇒ Object
get all the elements of the class.
- #alter_property(property, attribute: "DEFAULT", alteration:) ⇒ Object
-
#classname ⇒ Object
GET ###############.
-
#count(**args) ⇒ Object
Examples TestClass.count where: ‘last_access is NULL’ # only records where ‘last_access’ is not set TestClass.count # all records.
-
#create(**attributes) ⇒ Object
Universal method to create a new record.
-
#create_class(*c) ⇒ Object
creates an inherent class.
-
#create_index(name, **attributes) ⇒ Object
Pagination.create_property :col2, type: :integer Pagination.create_property :col3, type: :string Pagination.create_property :col4, type: :integer Pagination.create_index :composite, :on => [:col1, :col2, :col3], type: ‘dictionary’.
-
#create_properties(argument_hash, &b) ⇒ Object
Create more Properties in the Schema of the Class.
-
#create_property(field, type: :integer, index: nil, **args) ⇒ Object
Create a Property in the Schema of the Class and optionally create an automatic index.
-
#delete_property(field) ⇒ Object
Delete a property from the class.
-
#delete_record(*rid) ⇒ Object
(also: #delete_document)
Delete record(s) specified by their rid’s.
-
#delete_records(where: {}, **args) ⇒ Object
(also: #delete)
Query the database and delete the records of the resultset.
-
#first(**args) ⇒ Object
get the first element of the class.
-
#get(rid) ⇒ Object
get elements by rid.
-
#get_records(**args) ⇒ Object
(also: #get_documents)
»GetRecords« uses the REST-Interface to query the database.
-
#indexes ⇒ Object
list all Indexes.
-
#last(**args) ⇒ Object
get the last element of the class.
-
#link_list(*property) ⇒ Object
setter method to initialise a dummy ActiveOrient::Model class to enable multi-level access to links and linklists.
- #migrate_property(property, to:, linked_class: nil, via: 'tzr983') ⇒ Object
-
#namespace_prefix ⇒ Object
Set the namespace_prefix for database-classes.
-
#naming_convention(name = nil) ⇒ Object
NamingConvention provides a translation from database-names to class-names.
-
#orientdb_class(name:, superclass: nil) ⇒ Object
orientdb_class is used to refer a ActiveOrient:Model-Object providing its name.
-
#print_properties ⇒ Object
Print the properties of the class.
-
#properties ⇒ Object
(also: #get_class_properties)
Get the properties of the class.
-
#query(**args) ⇒ Object
returns a OrientSupport::OrientQuery.
-
#query_database(query, set_from: true) ⇒ Object
QueryDatabase sends the Query directly to the database.
-
#require_model_file(dir = nil) ⇒ Object
requires the file specified in the model-dir.
-
#update(where:, set: {}, **arg) ⇒ Object
same as update!, but returns a list of updated records.
-
#update!(where: nil, set: {}, **arg) ⇒ Object
(also: #update_all)
Sets a value to certain attributes, overwrites existing entries, creates new attributes if necessary.
-
#upsert(set: nil, where:, **args) ⇒ Object
Creates or updates records.
-
#where(*attributes) ⇒ Object
(also: #custom_where)
Performs a query on the Class and returns an Array of ActiveOrient:Model-Records.
Methods included from OrientSupport::Support
#as, #compose_where, #generate_sql_list, #while_s
Instance Method Details
#add_edge_link(name:, direction: :out, edge:) ⇒ Object
640 641 642 643 644 645 |
# File 'lib/model/the_class.rb', line 640 def add_edge_link name:, direction: :out, edge: dir = direction.to_s == "out" ? :out : :in define_method(name.to_sym) do return self["#{dir}_#{edge.classname}"].map{|x| x["in"]} end end |
#all ⇒ Object
get all the elements of the class
395 396 397 |
# File 'lib/model/the_class.rb', line 395 def all query.execute end |
#alter_property(property, attribute: "DEFAULT", alteration:) ⇒ Object
651 652 653 |
# File 'lib/model/the_class.rb', line 651 def alter_property property, attribute: "DEFAULT", alteration: # :nodoc: orientdb.alter_property self, property: property, attribute: attribute, alteration: alteration end |
#classname ⇒ Object
GET ###############
379 380 381 |
# File 'lib/model/the_class.rb', line 379 def classname # :nodoc: # ref_name end |
#count(**args) ⇒ Object
Examples
TestClass.count where: 'last_access is NULL' # only records where 'last_access' is not set
TestClass.count # all records
417 418 419 |
# File 'lib/model/the_class.rb', line 417 def count **args query( **( { projection: 'COUNT(*)' }.merge args )).execute(reduce: true){|x| x[:"COUNT(*)"]} end |
#create(**attributes) ⇒ Object
Universal method to create a new record. It’s overloaded to create specific kinds, eg. edge and vertex and is called only for abstract classes
Example:
V.create_class :test
Test.create string_attribute: 'a string', symbol_attribute: :a_symbol, array_attribute: [34,45,67]
Test.create link_attribute: Test.create( :a_new_attribute => 'new' )
174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/model/the_class.rb', line 174 def create **attributes attributes.merge :created_at => DateTime.new result = db.create_record self, attributes: attributes if result.nil logger.error('Model::Class'){ "Table #{refname}: create failed: #{attributes.inspect}" } elsif block_given? yield result else result # return value end end |
#create_class(*c) ⇒ Object
creates an inherent class
158 159 160 |
# File 'lib/model/the_class.rb', line 158 def create_class *c orientdb.create_class( *c ){ self } end |
#create_index(name, **attributes) ⇒ Object
Pagination.create_property :col2, type: :integer Pagination.create_property :col3, type: :string Pagination.create_property :col4, type: :integer Pagination.create_index :composite, :on => [:col1, :col2, :col3], type: ‘dictionary’
345 346 347 |
# File 'lib/model/the_class.rb', line 345 def create_index name, **attributes orientdb.create_index self, name: name, **attributes end |
#create_properties(argument_hash, &b) ⇒ Object
Create more Properties in the Schema of the Class
320 321 322 |
# File 'lib/model/the_class.rb', line 320 def create_properties argument_hash, &b orientdb.create_properties self, argument_hash, &b end |
#create_property(field, type: :integer, index: nil, **args) ⇒ Object
Create a Property in the Schema of the Class and optionally create an automatic index
Examples:
create_property :customer_id, type: :integer, index: :unique
create_property( :name, type: :string ) { :unique }
create_property( :name, type: :string ) { name: 'some_index', on: :automatic, type: :unique }
create_property :in, type: :link, linked_class: V (used by edges)
:call-seq: create_property(field (required), type: :a_supported_type’, linked_class: nil
supported types: :bool :double :datetime = :date :float :decimal
:embedded_list = :list :embedded_map = :map :embedded_set = :set
:int :integer :link_list :link_map :link_set
If ‘:list`, `:map`, `:set`, `:link`, `:link_list`, `:link_map` or `:link_set` is specified a `linked_class:` parameter can be specified. Argument is the OrientDB-Class-Constant
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 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 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 |
# File 'lib/model/the_class.rb', line 255 def create_property field, type: :integer, index: nil, **args arguments = args.values.map do |y| if y.is_a?(Class) && ActiveOrient.database_classes.values.include?(y) y.ref_name elsif ActiveOrient.database_classes.keys.include?(y.to_s) y else puts ActiveOrient.database_classes.inspect puts "YY : #{y.to_s} #{y.class}" raise ArgumentError , "database class #{y.to_s} not allocated" end end.compact.join(',') supported_types = { :bool => "BOOLEAN", :double => "BYTE", :datetime => "DATE", :date => "DATE", :float => "FLOAT", :decimal => "DECIMAL", :embedded_list => "EMBEDDEDLIST", :list => "EMBEDDEDLIST", :embedded_map => "EMBEDDEDMAP", :map => "EMBEDDEDMAP", :embedded_set => "EMBEDDEDSET", :set => "EMBEDDEDSET", :string => "STRING", :int => "INTEGER", :integer => "INTEGER", :link => "LINK", :link_list => "LINKLIST", :link_map => "LINKMAP", :link_set => "LINKSET", } ## if the »type« argument is a string, it is used unchanged type = supported_types[type] if type.is_a?(Symbol) raise ArgumentError , "unsupported type" if type.nil? s= " CREATE PROPERTY #{ref_name}.#{field} #{type} #{arguments}" puts s db.execute { s } i = block_given? ? yield : index ## supported format of block: index: { name: 'something' , on: :automatic, type: :unique } ## or { name: 'something' , on: :automatic, type: :unique } # ## or { some_name: :unique } # manual index ## or { :unique } # automatic index if i.is_a? Hash att= i.key( :index ) ? i.values.first : i name, on, type = if att.size == 1 && att[:type].nil? [att.keys.first, field, att.values.first ] else [ att[:name] || field , att[:on] || field , att[:type] || :unique ] end create_index( name , on: on, type: type) elsif i.is_a?(Symbol) || i.is_a?(String) create_index field, type: i end # orientdb.create_property self, field, **keyword_arguments, &b end |
#delete_property(field) ⇒ Object
Delete a property from the class
584 585 586 |
# File 'lib/model/the_class.rb', line 584 def delete_property field orientdb.delete_property self, field end |
#delete_record(*rid) ⇒ Object Also known as: delete_document
Delete record(s) specified by their rid’s
590 591 592 |
# File 'lib/model/the_class.rb', line 590 def delete_record *rid db.delete_record rid end |
#delete_records(where: {}, **args) ⇒ Object Also known as: delete
Query the database and delete the records of the resultset
Returns the count of datasets effected
598 599 600 601 602 603 604 605 606 |
# File 'lib/model/the_class.rb', line 598 def delete_records where: {} , **args if args[:all] == true where = {} else where.merge!(args) if where.is_a?(Hash) return 0 if where.empty? end orientdb.delete_records( self, where: where ).count end |
#first(**args) ⇒ Object
get the first element of the class
401 402 403 |
# File 'lib/model/the_class.rb', line 401 def first **args query( **( { order: "@rid" , limit: 1 }.merge args)).execute(reduce: true) end |
#get(rid) ⇒ Object
get elements by rid
385 386 387 388 389 390 391 |
# File 'lib/model/the_class.rb', line 385 def get rid if @excluded.blank? db.get_record(rid) else db.execute{ "select expand( @this.exclude( #{@excluded.map(&:to_or).join(",")})) from #{rid} "} end end |
#get_records(**args) ⇒ Object Also known as: get_documents
»GetRecords« uses the REST-Interface to query the database. The alternative »QueryDatabase« submits the query via Execute.
Both methods rely on OrientSupport::OrientQuery and its capacity to support complex query-builds. The method requires a hash of arguments. The following keys are supported:
projection:
SQL-Queries use »select« to specify a projection (ie. ‘select sum(a), b+5 as z from class where …`)
In ruby »select« is a method of enumeration. To specify what to »select« from in the query-string we use »projection«, which accepts different arguments
projection: a_string --> inserts the sting as it appears
projection: an OrientSupport::OrientQuery-Object --> performs a sub-query and uses the result for further querying though the given parameters.
projection: [a, b, c] --> "a, b, c" (inserts a comma-separated list)
projection: {a: b, "sum(x)" => f} --> "a as b, sum(x) as f" (renames properties and uses functions)
distinct:
Constructs a query like »select distinct(property) [as property] from …«
distinct: :property --> the result is mapped to the property »distinct«.
distinct: [:property] --> the result replaces the property
distinct: {property: :some_name} --> the result is mapped to ModelInstance.some_name
order:
Sorts the result-set. If new properties were introduced via select:, distinct: etc. Sorting takes place on these properties
order: :property {property: asc, property: desc}[property, property, .. ](orderdirection is 'asc')
Further supported Parameter:
group_by
skip
limit
unwind
see orientdb- documentation (https://orientdb.com/docs/last/SQL-Query.html)
query:
Instead of providing the parameter to »get_records«, a OrientSupport::OrientQuery can build and tested prior to the method-call. The OrientQuery-Object is then provided with the query-parameter. I.e.
q = OrientSupport::OrientQuery.new
ORD.create_class :test_model
q.from TestModel
q.where {name: 'Thomas'}
count = TestModel.count query: q
q.limit 10
0.step(count,10) do |x|
q.skip = x
puts TestModel.get_documents(query: q).map{|x| x.adress }.join('\t')
end
prints a Table with 10 columns.
496 497 498 |
# File 'lib/model/the_class.rb', line 496 def get_records **args db.get_records(from: self, **args){self} end |
#indexes ⇒ Object
list all Indexes
350 351 352 |
# File 'lib/model/the_class.rb', line 350 def indexes properties[:indexes] end |
#last(**args) ⇒ Object
get the last element of the class
408 409 410 |
# File 'lib/model/the_class.rb', line 408 def last **args query( **( { order: {"@rid" => 'desc'} , limit: 1 }.merge args)).execute(reduce: true) end |
#link_list(*property) ⇒ Object
setter method to initialise a dummy ActiveOrient::Model class to enable multi-level access to links and linklists
75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/model/the_class.rb', line 75 def link_list *property property.each do |p| the_dummy_class = orientdb.allocate_class_in_ruby("dummy_"+p.to_s) the_dummy_class.ref_name = ref_name + "." + p.to_s singleton_class.send :define_method, p do the_dummy_class end end end |
#migrate_property(property, to:, linked_class: nil, via: 'tzr983') ⇒ Object
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 |
# File 'lib/model/the_class.rb', line 355 def migrate_property property, to: , linked_class: nil, via: 'tzr983' if linked_class.nil? create_property via, type: to else create_property via, type: to, linked_class: linked_class end # my_count = query.kind(:update!).set( "#{via} = #{property} ").execute(reduce: true){|c| c[:count]} # logger.info{" migrate property: #{count} records prosessed"} all.each{ |r| r.update set:{ via => r[property.to_sym] }} nullify = query.kind(:update!).set( property: nil ).execute(reduce: true){|c| c[:count]} # raise "migrate property: count of erased items( #{nullify} differs from total count (#{my_count}) " if nullify != my_count db.execute{" alter property #{ref_name}.#{via} name '#{property}' "} logger.info{ "successfully migrated #{property} to #{:to} " } end |
#namespace_prefix ⇒ Object
Set the namespace_prefix for database-classes.
If a namespace is set by
ActiveOrient::Init.define_namespace { ModuleName }
ActiveOrient translates this to
ModuleName::CamelizedClassName
The database-class becomes
modulename_class_name
If the namespace is set to a class (Object, ActiveOrient::Model ) namespace_prefix returns an empty string.
Override to change its behavior
51 52 53 |
# File 'lib/model/the_class.rb', line 51 def namespace_prefix namespace.is_a?(Class )? '' : namespace.to_s.downcase+'_' end |
#naming_convention(name = nil) ⇒ Object
NamingConvention provides a translation from database-names to class-names.
It can be overwritten to provide different conventions for different classes, eg. Vertexes or edges and to introduce distinct naming-conventions in different namespaces
To overwrite use
class Model # < ActiveOrient::Model[:: ...]
def self.naming_convention
( conversion code )
end
end
25 26 27 28 29 30 31 32 33 34 |
# File 'lib/model/the_class.rb', line 25 def naming_convention name=nil nc = name.present?? name.to_s : ref_name if namespace_prefix.present? nc.split(namespace_prefix).last.camelize else nc.camelize end rescue nil end |
#orientdb_class(name:, superclass: nil) ⇒ Object
orientdb_class is used to refer a ActiveOrient:Model-Object providing its name
Parameter: name: string or symbol
60 61 62 63 64 65 66 67 |
# File 'lib/model/the_class.rb', line 60 def orientdb_class name:, superclass: nil # :nodoc: # public method: autoload_class ActiveOrient.database_classes[name.to_s].presence || ActiveOrient::Model rescue NoMethodError => e logger.error { "Error in orientdb_class: is ActiveOrient.database_classes initialized ? \n\n\n" } logger.error{ e.backtrace.map {|l| " #{l}\n"}.join } Kernel.exit end |
#print_properties ⇒ Object
Print the properties of the class
431 432 433 |
# File 'lib/model/the_class.rb', line 431 def print_properties orientdb.print_class_properties self end |
#properties ⇒ Object Also known as: get_class_properties
Get the properties of the class
423 424 425 426 |
# File 'lib/model/the_class.rb', line 423 def properties object = orientdb.get_class_properties self {:properties => object['properties'], :indexes => object['indexes']} end |
#query(**args) ⇒ Object
returns a OrientSupport::OrientQuery
188 189 190 |
# File 'lib/model/the_class.rb', line 188 def query **args OrientSupport::OrientQuery.new( **( {from: self}.merge args)) end |
#query_database(query, set_from: true) ⇒ Object
QueryDatabase sends the Query directly to the database.
The query returns a hash if a result set is expected
select {something} as {result} (...)
leads to
[ { :{result} => {result of query} } ]
It can be modified further by passing a block, ie.
q = OrientSupport::OrientQuery.new( from: :base )
.projection( ‘first_list.second_list as second_list’ ) .where( label: 9 )
q.to_s => 'select first_list[5].second_list[9] as second_list from base where label = 9 '
second_list = Base.query_database( q ){|x| x}.first
The query returns (a list of) documents of type ActiveOrient::Model if a document is queried i.e.
q = OrientSupport::OrientQuery.new from: :base q.projection ‘expand( first_list.second_list)’ #note: no ‘as’ statement result2 = Base.query_database( q ).first => #<SecondList:0x000000000284e840 @metadata={}, @d=nil, @attributes=“@class”=>“second_list”>
query_database is used on model-level and submits
select (...) from class
#query performs queries on the instance-level and submits
select (...) from #{a}:{b}
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 |
# File 'lib/model/the_class.rb', line 564 def query_database query, set_from: true # note: the parameter is not used anymore query.from self if query.is_a?(OrientSupport::OrientQuery) && query.from.nil? result = db.execute{ query.to_s } result = if block_given? result.is_a?(Array) ? result.map{|x| yield(x) } : yield(result) else result end if result.is_a? Array OrientSupport::Array.new work_on: self, work_with: result else result end # return value end |
#require_model_file(dir = nil) ⇒ Object
requires the file specified in the model-dir
In fact, the model-files are loaded instead of required. Thus, even after recreation of a class (Class.delete_class, ORD.create_class classname) custom methods declared in the model files are present.
If a class is destroyed (i.e. the database class is deleted), the ruby-class and its methods vanish, too.
The directory specified is expanded by the namespace. The parameter itself is the base-dir.
Example:
Namespace: HC
model_dir : 'lib/model'
searched directory: 'lib/model/hc'
ActiveOrient::Model.modeldir is aimed to be set to the application dir. It may be a String, Pathname or an array of strings or pathnames.
The parameter ‘dir` is used internally and by gems to ensure that basic methods are loaded first.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/model/the_class.rb', line 111 def require_model_file dir = nil logger.progname = 'ModelClass#RequireModelFile' # model-dir can either be a string or an array of string or pathnames default = [ActiveOrient::Model.model_dir].flatten # access the default dir's first the_directories = case dir when String, Pathname default.present? ? [dir] + default : [dir] when Array default.present? ? dir + default : dir else default.present? ? default : [] end.uniq.compact the_directories.uniq.map do |raw_directory| the_directory = Pathname( raw_directory ) if File.exists?( the_directory ) model= self.to_s.underscore + ".rb" filename = the_directory + model if File.exists?(filename ) if load filename logger.debug{ "#{filename} sucessfully loaded" } self #return_value else logger.error{ "#{filename} load error" } nil #return_value end else logger.debug{ "model-file not present: #{filename} --> skipping" } nil #return_value end else logger.error{ "Directory #{ the_directory } not present " } nil #return_value end end.compact.present? # return true only if at least one model-file is present rescue TypeError => e puts "THE CLASS#require_model_file -> TypeError: #{e.}" puts "Working on #{self.to_s} -> #{self.superclass}" puts "Class_hierarchy: #{orientdb.class_hierarchy.inspect}." print e.backtrace.join("\n") raise # end |
#update(where:, set: {}, **arg) ⇒ Object
same as update!, but returns a list of updated records
227 228 229 230 231 |
# File 'lib/model/the_class.rb', line 227 def update where: , set: {}, **arg # In OrientDB V.3 the database only returns the affected rid's # We have to update the contents manually, this is done in the execute-block query( kind: :update, set: set.merge(arg), where: where).execute{|y| y[:$current].reload!} end |
#update!(where: nil, set: {}, **arg) ⇒ Object Also known as: update_all
Sets a value to certain attributes, overwrites existing entries, creates new attributes if necessary
returns the count of affected records
IB::Account.update connected: false
IB::Account.update where: "account containsText 'F'", set:{ connected: false }
# or
IB::Account.update connected: false, where: "account containsText 'F'"
219 220 221 |
# File 'lib/model/the_class.rb', line 219 def update! where: nil , set: {}, **arg query( kind: :update!, set: set.merge(arg), where: where).execute(reduce: true){|y| y[:count]} end |
#upsert(set: nil, where:, **args) ⇒ Object
Creates or updates records. Parameter:
-
set: A hash of attributes to insert or update unconditionally
-
where: A string or hash as condition which should return just one record.
The where-part should be covered with an unique-index.
returns the affected record, if the where-condition is set properly. Otherwise upsert acts as »update« and returns all updated records (as array).
204 205 206 207 |
# File 'lib/model/the_class.rb', line 204 def upsert set: nil, where: , **args set = where if set.nil? query( **args.merge( kind: :upsert, set: set, where: where )).execute(reduce: true){|y| y[:$current].reload!} end |
#where(*attributes) ⇒ Object Also known as: custom_where
Performs a query on the Class and returns an Array of ActiveOrient:Model-Records.
Fall-back method, is overloaded by Vertex.where
Is aliased by »custom_where»
Example:
Log.where priority: 'high'
--> submitted database-request: query/hc_database/sql/select from Log where priority = 'high'/-1
=> [ #<Log:0x0000000480f7d8 @metadata={ ... }, ...
Multiple arguments are joined via “and” eg:
Aktie.where symbol: 'TSL, exchange: 'ASX'
---> select from aktie where symbol = 'TLS' and exchange = 'ASX'
520 521 522 523 |
# File 'lib/model/the_class.rb', line 520 def where *attributes q= OrientSupport::OrientQuery.new where: attributes query_database( q) end |