lib/support/orient.rb in active-orient-0.79 vs lib/support/orient.rb in active-orient-0.80
- old
+ new
@@ -4,12 +4,27 @@
# The Array _knows_ its database-class. This enables database-transactions outside the scope
# of ActiveOrient
#
# The Database-Class is available through Array#record
-
-
+#
+# *caution:*
+# Don't mix ActiveOrient::Array's with conventional ones
+# > t= G21.first
+# > t.ll
+# => ["test", "test_2", 5, 8, 7988, "uzg"]
+# > t.ll = [9,6,7] # This is an assignment of an Array to the variable »ll»
+# # It does NOT call ActiveOrient::Array#=[].
+# => [9, 6, 7] # Instead an Array is assigned to the variable »ll»
+#
+# it is only updated localy, as shown if we reload the document
+# > t= G21.first.attributes
+# => {:ll=>["test", "test_2", 5, 8, 7988, "uzg"]}
+#
+# Thus its imperativ to safe the changes made.
+
+
class Array < Array
include OrientSupport::Support
=begin
During initialisation the model-instance to work on is stored in @orient.
@@ -31,11 +46,11 @@
def initialize( work_on:, work_with: )
@orient = work_on.class == Class ? work_on.new : work_on
super work_with
begin
- @name = @orient.attributes.key(self)
+ @name = block_given? ? yield : @orient.attributes.key(self)
rescue TypeError => e # not defined
ActiveOrient::Base.logger.debug{ "--------------------Type Error ----------------------------------" }
ActiveOrient::Base.logger.debug("OrientSupport::Array"){ "Attributes #{@orient.attributes.inspect}" }
ActiveOrient::Base.logger.debug("OrientSupport::Array"){ e.inspect
ActiveOrient::Base.logger.debug{ "indicates a try to access a non existing array element" }}
@@ -45,11 +60,10 @@
ActiveOrient::Base.logger.debug ("OrientSupport::Array"){ e.inspect }
#ActiveOrient::Base.logger.error{ e.backtrace.map {|l| " #{l}\n"}.join }
ActiveOrient::Base.logger.debug{ "due to a bug in ActiveSupport DateTime Calculations" }
# we just ignore the error
end
- @name = yield if @name.nil? && block_given?
end
def as_json o=nil
map{|x| x.rid? ? x.rid : x }
end
@@ -58,64 +72,145 @@
end
def to_human
map &:to_human
end
-# returns the modified array and is chainable
+=begin
+
+Appends the arguments to the Array.
+
+Returns the modified database-document (not the array !!)
+=end
+ def append *arg
+
+ @orient.update { "set #{@name.to_s} = #{@name} || #{arg.to_or} "}[@name] if check_if_complete
+ @orient.reload!
+ end
+=begin
+Append the argument to the Array, changes the Array itself.
+
+Returns the modified Array ( and is chainable )
#
# i= V.get( '89:0')
# ii=i.zwoebelkuchen << 'z78' << 6 << [454, 787]
# => [7, 5, 6, "z78", 78, 45, "z78", 6, 454, 787]
-=begin
-Append the argument to the Array, changes the Array itself.
The change is immediately transmitted to the database.
+The difference to `append`: that method accepts a komma separated list of arguments
+and returns the modified database-document. `<<` accepts only one argument. An
+Array is translated into multi-arguments of `append`
-=end
- def append *arg
+ > t = G21.create ll: ['test','test_2', 5, 8 , 7988, "uzg"]
+ INFO->CREATE VERTEX ml_g21 CONTENT {"ll":["test","test_2",5,8,7988,"uzg"]}
+ => #<ML::G21:0x0000000002622cb0 @metadata={:type=>"d", :class=>"ml_g21", :version=>1,
+ :fieldTypes=>nil, :cluster=>271, :record=>0},
+ @attributes={:ll=>["test", "test_2", 5, 8, 7988, "uzg"]}>
+ > t.ll << [9,10]
+ INFO->update #271:0 set ll = ll || [9, 10] return after @this
+ => ["test", "test_2", 5, 8, 7988, "uzg"]
+ > t.ll << [9,10] << 'u'
+ INFO->update #271:0 set ll = ll || [9, 10] return after @this
+ INFO->update #271:0 set ll = ll || ['u'] return after @this
+ => ["test", "test_2", 5, 8, 7988, "uzg", 9, 10]
- @orient.update { "#{@name.to_s} = #{@name} || #{arg.to_or} "}[@name]
+
+The Array can be treated separately
+
+ > z = t.ll
+ => ["test", "test_2", 5, 8, 7988, "uzg"]
+ > z << 78
+ INFO->update #272:0 set ll = ll || [78] return after @this
+ => ["test", "test_2", 5, 8, 7988, "uzg", 78]
+
+=end
+ def << arg
+ append( *arg).send @name
end
- alias << append
+=begin
+Removes the specified list entries from the Array
+
+Returns the modified Array (and is chainable).
+
+ > t= G21.first
+ > t.ll
+ => ["test", "test_2", 7988, "uzg", 6789, "xvy"]
+ > u= t.ll << 'xvz'
+ # INFO->update #272:0 set ll = ll || ['xvz'] return after @this
+ => ["test", "test_2", 7988, "uzg", 6789, "xvy", "xvz"]
+ > z= u.remove 'xvy'
+ # INFO->update #272:0 remove ll = 'xvy' return after @this
+ => ["test", "test_2", 7988, "uzg", 6789, "xvz"]
+
+The ModelInstance is updated, too, as shown by calling
+
+> t.ll
+ => ["test", "test_2", 7988, "uzg", 6789, "xvz"]
+
+
+Thus
+
+ > t.ll.remove 7988
+ # INFO->update #272:0 remove ll = 7988 return after @this
+ => ["test", "test_2", "uzg", 6789, "xvz"]
+
+returns thea modified Array
+=end
def remove *k
# todo combine queries in a transaction
- puts "delete: #{@name} --< #{k.map(&:to_or).join( ' :: ' )}"
- k.each{|item| @orient.remove( " #{@name} = #{item.to_or}")[@name] }
+ ActiveOrient::Base.logger.debug { "delete: #{@name} --< #{k.map(&:to_or).join( ' :: ' )}"}
+ k.map{|l| @orient.update( {remove: { @name => l} } ) }
+ # @orient.reload!
+ # @orient.send @name
end
+ def remove_by_index index
+ @orient.update( { remove: { @name => "#{@name[index]}" } } )
+ end
-
+def check_if_complete
+ if @name.blank?
+ @orient.logger.warn{ "Database is uneffected. Operation is incomplete/ not allowed" }
+ false
+ else
+ true
+ end
+end
=begin
Updating of single items
=end
-
def []= key, value
super
- @orient.update set: {@name => self} if @name.present?
+ @orient.update set: {@name => self} if @name.present? if check_if_complete
end
###
## just works with Hashes as parameters
def where *item
where_string = item.map{|m| where_string = compose_where( m ) }.join(' and ')
subquery= OrientSupport::OrientQuery.new from: @orient, projection: "expand( #{@name})"
q= OrientSupport::OrientQuery.new from: subquery, where: item
- @orient.query q.to_s
+ @orient.db.execute{ q.to_s } if check_if_complete
end
- def method_missing *args
-
- self.map{|x| x.send *args }
+ def method_missing method, *args
+ return if empty?
+ if @orient.is_a? ActiveOrient::Model # IB::Model
+ # delegate to public methods
+ self.map{|x| x.public_send(method, *args)}
+ else
+ self.map{|x| x.send method, *args }
+ end
rescue NoMethodError => e
- ActiveOrient::Base.logger.error("OrientSupport::Array"){ "MethodMissing -> Undefined method: #{args.first} -- Args: #{args[1..-1].inspect}"}
+ ActiveOrient::Base.logger.error("OrientSupport::Array"){ "#{self.inspect} MethodMissing -> Undefined method: #{args.first} -- Args: #{args[1..-1].inspect}"}
ActiveOrient::Base.logger.error {" The Message #{e.message}"}
ActiveOrient::Base.logger.error{ e.backtrace.map {|l| " #{l}\n"}.join }
+ raise
end
end #Class
@@ -123,74 +218,88 @@
class Hash < Hash # WithIndifferentAccess
include OrientSupport::Support
def initialize modelinstance, args
super()
- # puts "Hash.new args #{args}"
@orient = modelinstance
self.merge! args
- @name = modelinstance.attributes.key(self)
- @name = yield if @name.nil? && block_given?
- # puts "@name #{@name}"
+ @name = block_given? ? yield : modelinstance.attributes.key(self)
self
end
-
- def []= k, v
- @orient.update { "#{@name.to_s}.#{k.to_s} = #{v.to_or}" }
+ def store k, v
+ @orient.update { "set #{@name}[#{k.to_s.to_or}] = #{v.to_or} "}[@name] #if check_if_complete
+ @orient.reload!
end
-# Inserts the provided Hash to the (possibly emty) list-property and returns a hash
- def append arg
- # the argument is simply provided as JSON-parameter to »update«
- # generated query: update {rrid} set { @name } = { arg.to_json } return after @this
- # todo : consider returning a OrientSuport::Hash
- @orient.update { "#{@name.to_s} = "+ arg.to_json }[@name]
+ alias []= store
+
+
+# Inserts the provided Hash to the (possibly empty) list-property and updates the dataset
+ #
+ # Keys are translated to symbols
+ #
+ def merge **arg
+ @orient.update @name => super(**arg)
+ @orient.reload!
end
- alias << append
+ alias << merge
# removes a key-value entry from the hash.
#
-# parameter: list of key's (duplicate values are removed)
+# parameter: list of key's
+#
+# returns the modified OrientSupport::Hash
+ #
+ # ie, given
+ # b => <Base[51:0]: < Base: 51:0 >, a_set : {:warrant_value=>["8789", "HKD"], :what_if_pm_enabled=>["true", ""], :t_bill_value=>["0", "HKD"]}>
+ # c= b.a_set.remove :warrant_value
+ # INFO->update #51:0 remove a_set = 'warrant_value' return after $current
+ # c => {:what_if_pm_enabled=>["true", ""], :t_bill_value=>["0", "HKD"]}
+
+
def remove *k
# todo combine queries in a transaction
- k.map{ |key| @orient.update( remove: true ) { "#{@name.to_s}.#{key} " } }.last
+
+ r= k.map{|key| @orient.update{ "remove #{@name} = #{key.to_s.to_or} " } }
+ @orient.reload!.send @name
+
end
- # def delete *key
-#
-# key.each do | k |
-# o = OrientSupport::OrientQuery.new from: @orient,
-# kind: 'update',
-# set: "#{@name}.#{k.to_s}",
-# return: "$current.#{@name}"
-# @orient.db.execute{ o.to_s.gsub( 'set ', 'remove ' ) }.first.send( @name ) # extracts the modified array (from DB) from the result
-# end
-# @orient.reload!
-# @orient.send @name # return value
-# end
def delete_if &b
super &b
@orient.update set:{ @name => self}
end
-
+ # slice returns a subset of the hash
+ #
+ # excepts a regular expression as well
+ def slice arg
+ if arg.is_a? Regexp
+ find_all{ |key| key.to_s.match(arg) }.to_h
+ else
+ super arg.to_sym
+ end
+ end
+ def [] arg
+ super
+ end
end
end #Module
class Hash
def to_human
"{ " + self.map{ |k,v| [k.to_s,": ", v.to_orient].join }.join(', ') + " }"
end
- def coerce arg
- if arg.is_a? DateTime
- nil
- else
- super
-
- end
- end
+ # def coerce arg
+ # if arg.is_a? DateTime
+ # nil
+ # else
+ # super
+#
+# end
+# end
end