Class: TaliaCore::ActiveSource
- Extended by:
- TaliaCore::ActiveSourceParts::ClassMethods, TaliaCore::ActiveSourceParts::Finders, TaliaCore::ActiveSourceParts::PredicateHandler::ClassMethods, TaliaCore::ActiveSourceParts::SqlHelper, TaliaUtil::Progressable
- Includes:
- ActiveRDF::ResourceLike, TaliaCore::ActiveSourceParts::PredicateHandler, TaliaCore::ActiveSourceParts::RdfHandler
- Defined in:
- lib/talia_core/active_source.rb
Overview
This class encapsulate the basic “Source” behaviour for an element in the semantic store. This is the baseclass for all things that are represented as an “Resource” (with URL) in the semantic store.
If an object is modified but not saved, the ActiveSource does not guarantee that the RDF will always be in sync with the database. However, a subsequent saving of the object will re-sync the RDF.
An effort is made to treat RDF and database writes in the same way, so that they should usually be in sync:
-
Write operations are usually lazy, the data should only be saved once save! is called. However, ActiveRecord may still decide that the objects need to be saved if they are involved in other operations.
-
Operations that clear a predicate are immediate. That also means that using singular property setter, if used will immediately erase the old value. If the record is not saved, the property will be left empty (and not revert to the original value!)
Direct Known Subclasses
Instance Method Summary collapse
-
#[](attribute) ⇒ Object
(also: #get_attribute)
Works in the normal way for database attributes.
-
#[]=(attribute, value) ⇒ Object
Assignment to an attribute.
-
#add_additional_rdf_types ⇒ Object
Add the additional types to the source that were configured in the class.
-
#add_semantic_attributes(overwrite, attributes) ⇒ Object
Helper to update semantic attributes from the given hash.
-
#attach_files(files) ⇒ Object
Attaches files from the given hash.
-
#data(type = nil, location = nil) ⇒ Object
This will return a list of DataRecord objects.
-
#db_attr?(attribute) ⇒ Boolean
True if the given attribute is a database attribute.
- #defined_property?(prop_name) ⇒ Boolean
-
#direct_predicates ⇒ Object
Gets the direct predicates (using the database).
-
#inverse ⇒ Object
Returns a special object which collects the “inverse” properties of the Source - these are all RDF properties which have the current Source as the object.
-
#inverse_predicates ⇒ Object
Gets the inverse predicates.
-
#predicate(namespace, name) ⇒ Object
Accessor that allows to lookup a namespace/name combination.
-
#predicate_replace(namespace, name, value) ⇒ Object
Replaces the given predicate with the value.
-
#predicate_set(namespace, name, value) ⇒ Object
Setter method for predicates by namespace/name combination.
-
#predicate_set_uniq(namespace, name, value) ⇒ Object
Setter method that will only add the value if it doesn’t exist already.
- #property_options_for(property) ⇒ Object
-
#rdf_selftype ⇒ Object
The RDF type that is used for objects of the current class.
- #reload ⇒ Object
-
#rewrite_attributes(attributes) {|_self| ... } ⇒ Object
Works like update_attributes, but will replace the semantic attributes rather than adding to them.
-
#rewrite_attributes!(attributes) {|_self| ... } ⇒ Object
Like rewrite_attributes, but calling save!.
-
#short_uri ⇒ Object
Uri in short notation.
-
#to_rdf ⇒ Object
Creates an RDF/XML resprentation of the source.
-
#to_s ⇒ Object
To string: Just return the URI.
-
#to_uri ⇒ Object
Create a new uri object.
-
#to_xml ⇒ Object
XML Representation of the source.
-
#update_attributes(attributes) {|_self| ... } ⇒ Object
Updates all attributes of this source.
-
#update_attributes!(attributes) {|_self| ... } ⇒ Object
As update_attributes, but uses save! to save the source.
-
#update_attributes_orig ⇒ Object
Make aliases for the original updating methods.
- #update_attributes_orig! ⇒ Object
-
#update_source(properties, mode) ⇒ Object
Updates the source with the given properties.
-
#value_for(thing) ⇒ Object
Helper.
-
#write_predicate_direct(predicate, value) ⇒ Object
Writes the predicate directly to the database and the rdf store.
Methods included from TaliaCore::ActiveSourceParts::ClassMethods
additional_rdf_types, create_from_xml, create_multi_from, create_source, exists?, expand_uri, new, paginate, props_to_destroy, rewrite, split_attribute_hash, update
Methods included from TaliaCore::ActiveSourceParts::Finders
count, find, find_by_partial_local, find_by_partial_uri, find_by_uri_token
Methods included from TaliaCore::ActiveSourceParts::SqlHelper
default_inv_joins, default_joins, props_join, sources_join
Methods included from TaliaCore::ActiveSourceParts::PredicateHandler::ClassMethods
Methods included from TaliaUtil::Progressable
progressor, progressor=, run_with_progress
Methods included from TaliaCore::ActiveSourceParts::RdfHandler
#autosave_rdf=, #autosave_rdf?, #create_rdf, #my_rdf
Methods included from TaliaCore::ActiveSourceParts::PredicateHandler
#each_cached_wrapper, #get_objects_on, #get_wrapper_on, #has_type?, #inject_predicate, #reset!, #save_wrappers, #types
Instance Method Details
#[](attribute) ⇒ Object Also known as: get_attribute
Works in the normal way for database attributes. If the value is not an attribute, it tries to find objects related to this source with the value as a predicate URL and returns a collection of those.
The assignment operator remains as it is for the ActiveRecord.
99 100 101 102 103 104 105 106 107 |
# File 'lib/talia_core/active_source.rb', line 99 def [](attribute) if(db_attr?(attribute)) super(attribute) elsif(defined_property?(attribute)) self.send(attribute) else get_objects_on(attribute) end end |
#[]=(attribute, value) ⇒ Object
Assignment to an attribute. This will overwrite all current triples.
111 112 113 114 115 116 117 118 119 |
# File 'lib/talia_core/active_source.rb', line 111 def []=(attribute, value) if(db_attr?(attribute)) super(attribute, value) elsif(defined_property?(attribute)) self.send("#{attribute}=", value) else get_wrapper_on(attribute).replace(value) end end |
#add_additional_rdf_types ⇒ Object
Add the additional types to the source that were configured in the class. Usually this will not need to be called directly, but will be automatically called during construction.
This will check the existing types to avoid duplication
341 342 343 344 345 346 347 348 349 350 351 |
# File 'lib/talia_core/active_source.rb', line 341 def add_additional_rdf_types # return if(self.class.additional_rdf_types.empty?) type_hash = {} self.types.each { |type| type_hash[type.respond_to?(:uri) ? type.uri.to_s : type.to_s] = true } # Add the "class" default type type (unless this is the source for the self type itself).0 self.types << rdf_selftype unless(type_hash[rdf_selftype.to_s] || (rdf_selftype.to_s == self.uri.to_s)) # Add the user-configured types self.class.additional_rdf_types.each do |type| self.types << type unless(type_hash[type.respond_to?(:uri) ? type.uri.to_s : type.to_s]) end end |
#add_semantic_attributes(overwrite, attributes) ⇒ Object
Helper to update semantic attributes from the given hash. If there is a “<value>” string, it will be treated as a reference to an URI. Hash values may be arrays.
If overwrite is set to yes, the given attributes (and only those) are replaced with the values from the hash. Otherwise the attribute values will be added to the existing ones
209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/talia_core/active_source.rb', line 209 def add_semantic_attributes(overwrite, attributes) attributes.each do |attr, value| if(defined_property?(attr)) self[attr] = value else attr_wrap = self[attr] attr_wrap.remove if(overwrite) value.to_a.each { |val| self[attr] << target_for(val) } end end end |
#attach_files(files) ⇒ Object
Attaches files from the given hash. See the new method on ActiveSource for the details.
The call in this case should look like this:
attach_files([{ url => 'url_or_filename', :options => { .. }}, ...])
Have a look at the DataLoader module to see how the options work. You may also provide a single hash for :files (instead of an array) if you have just one file. Files will be saved immediately.
363 364 365 366 367 368 369 370 371 372 373 |
# File 'lib/talia_core/active_source.rb', line 363 def attach_files(files) files = [ files ] unless(files.is_a?(Array)) files.each do |file| file. filename = file[:url] assit(filename) = file[:options] || {} records = DataTypes::FileRecord.create_from_url(filename, ) records.each { |rec| self.data_records << rec } end end |
#data(type = nil, location = nil) ⇒ Object
This will return a list of DataRecord objects. Without parameters, this returns all data elements on the source. If a type is given, it will return only the elements of the given type. If both type and location are given, it will retrieve only the specified data element
379 380 381 382 383 384 385 386 |
# File 'lib/talia_core/active_source.rb', line 379 def data(type = nil, location= nil) find_type = location ? :first : :all # Find just one element if a location is given type = type.name if(type.is_a?(Class)) = {} [:conditions] = [ "type = ?", type ] if(type && !location) [:conditions] = [ "type = ? AND location = ?", type, location ] if(type && location) data_records.find(find_type, ) end |
#db_attr?(attribute) ⇒ Boolean
True if the given attribute is a database attribute
287 288 289 |
# File 'lib/talia_core/active_source.rb', line 287 def db_attr?(attribute) ActiveSource.db_attr?(attribute) end |
#defined_property?(prop_name) ⇒ Boolean
291 292 293 |
# File 'lib/talia_core/active_source.rb', line 291 def defined_property?(prop_name) self.class.defined_property?(prop_name) end |
#direct_predicates ⇒ Object
Gets the direct predicates (using the database)
273 274 275 276 277 |
# File 'lib/talia_core/active_source.rb', line 273 def direct_predicates raise(ActiveRecord::RecordNotFound, "Cannot do this on unsaved record.") if(new_record?) rels = SemanticRelation.find_by_sql("SELECT DISTINCT predicate_uri FROM semantic_relations WHERE subject_id = #{self.id}") rels.collect { |rel| N::Predicate.new(rel.predicate_uri) } end |
#inverse ⇒ Object
Returns a special object which collects the “inverse” properties of the Source - these are all RDF properties which have the current Source as the object.
The returned object supports the [] operator, which allows to fetch the “inverse” (the RDF subjects) for the given predicate.
Example: person.inverse[N::FOO::creator]
would return a list of all the elements of which the current person is the creator.
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'lib/talia_core/active_source.rb', line 230 def inverse inverseobj = Object.new inverseobj.instance_variable_set(:@assoc_source, self) class << inverseobj def [](property) @assoc_source.subjects.find(:all, :conditions => { 'semantic_relations.predicate_uri' => property.to_s } ) end private :type end inverseobj end |
#inverse_predicates ⇒ Object
Gets the inverse predicates
280 281 282 283 284 |
# File 'lib/talia_core/active_source.rb', line 280 def inverse_predicates raise(ActiveRecord::RecordNotFound, "Cannot do this on unsaved record.") if(new_record?) rels = SemanticRelation.find_by_sql("SELECT DISTINCT predicate_uri FROM semantic_relations WHERE object_id = #{self.id}") rels.collect { |rel| N::Predicate.new(rel.predicate_uri) } end |
#predicate(namespace, name) ⇒ Object
Accessor that allows to lookup a namespace/name combination. This works like the [] method: I will return an array-like object on predicates can be manipulated.
249 250 251 |
# File 'lib/talia_core/active_source.rb', line 249 def predicate(namespace, name) get_objects_on(get_namespace(namespace, name)) end |
#predicate_replace(namespace, name, value) ⇒ Object
Replaces the given predicate with the value. Good for one-value predicates
266 267 268 269 270 |
# File 'lib/talia_core/active_source.rb', line 266 def predicate_replace(namespace, name, value) pred = predicate(namespace, name) pred.remove pred << value end |
#predicate_set(namespace, name, value) ⇒ Object
Setter method for predicates by namespace/name combination. This will *add a precdicate triple, not replace one!*
255 256 257 |
# File 'lib/talia_core/active_source.rb', line 255 def predicate_set(namespace, name, value) predicate(namespace, name) << value end |
#predicate_set_uniq(namespace, name, value) ⇒ Object
Setter method that will only add the value if it doesn’t exist already
260 261 262 263 |
# File 'lib/talia_core/active_source.rb', line 260 def predicate_set_uniq(namespace, name, value) pred = predicate(namespace, name) pred << value unless(pred.include?(value)) end |
#property_options_for(property) ⇒ Object
295 296 297 |
# File 'lib/talia_core/active_source.rb', line 295 def (property) self.class.(property) end |
#rdf_selftype ⇒ Object
The RDF type that is used for objects of the current class
389 390 391 |
# File 'lib/talia_core/active_source.rb', line 389 def rdf_selftype (N::TALIA + self.class.name.demodulize) end |
#reload ⇒ Object
393 394 395 396 |
# File 'lib/talia_core/active_source.rb', line 393 def reload reset! # Clear the property cache super end |
#rewrite_attributes(attributes) {|_self| ... } ⇒ Object
Works like update_attributes, but will replace the semantic attributes rather than adding to them.
191 192 193 194 |
# File 'lib/talia_core/active_source.rb', line 191 def rewrite_attributes(attributes) yield self if(block_given?) update_attributes_orig(process_attributes(true, attributes)) end |
#rewrite_attributes!(attributes) {|_self| ... } ⇒ Object
Like rewrite_attributes, but calling save!
197 198 199 200 |
# File 'lib/talia_core/active_source.rb', line 197 def rewrite_attributes!(attributes) yield self if(block_given?) update_attributes_orig!(process_attributes(true, attributes)) end |
#short_uri ⇒ Object
Uri in short notation
74 75 76 |
# File 'lib/talia_core/active_source.rb', line 74 def short_uri N::URI.new(self.uri).to_name_s end |
#to_rdf ⇒ Object
Creates an RDF/XML resprentation of the source. The object is saved if this is a new record.
331 332 333 334 |
# File 'lib/talia_core/active_source.rb', line 331 def to_rdf save! if(new_record?) ActiveSourceParts::Xml::RdfBuilder.build_source(self) end |
#to_s ⇒ Object
To string: Just return the URI. Use to_xml if you need something more involved.
85 86 87 |
# File 'lib/talia_core/active_source.rb', line 85 def to_s self[:uri] end |
#to_uri ⇒ Object
Create a new uri object
90 91 92 |
# File 'lib/talia_core/active_source.rb', line 90 def to_uri self[:uri].to_uri end |
#to_xml ⇒ Object
XML Representation of the source. The object is saved if this is a new record.
324 325 326 327 |
# File 'lib/talia_core/active_source.rb', line 324 def to_xml save! if(new_record?) ActiveSourceParts::Xml::SourceBuilder.build_source(self) end |
#update_attributes(attributes) {|_self| ... } ⇒ Object
Updates all attributes of this source. For the database attributes, this works exactly like ActiveRecord::Base#update_attributes
If semantic attributes are present, they will be updated on the semantic store.
After the update, the source will be saved.
178 179 180 181 |
# File 'lib/talia_core/active_source.rb', line 178 def update_attributes(attributes) yield self if(block_given?) super(process_attributes(false, attributes)) end |
#update_attributes!(attributes) {|_self| ... } ⇒ Object
As update_attributes, but uses save! to save the source
184 185 186 187 |
# File 'lib/talia_core/active_source.rb', line 184 def update_attributes!(attributes) yield self if(block_given?) super(process_attributes(false, attributes)) end |
#update_attributes_orig ⇒ Object
Make aliases for the original updating methods
122 |
# File 'lib/talia_core/active_source.rb', line 122 alias :update_attributes_orig :update_attributes |
#update_attributes_orig! ⇒ Object
123 |
# File 'lib/talia_core/active_source.rb', line 123 alias :update_attributes_orig! :update_attributes! |
#update_source(properties, mode) ⇒ Object
Updates the source with the given properties. The ‘mode’ field indicates if and how the update will be performed. See the ImportJobHelper class for the different modes.
As opposed to the *_attributes method, this will also handle file elements. The default mode is :skip (do nothing)
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/talia_core/active_source.rb', line 132 def update_source(properties, mode) properties. mode = :update if(self.is_a?(SourceTypes::DummySource)) # Dummy sources are always updated mode ||= :skip mode = mode.to_sym return self if(mode == :skip) # If we're told to ignore updates # Deal with already existing sources files = properties.delete(:files) if(mode == :overwrite) # If we are to overwrite, delete all relations and update normally self.semantic_relations.destroy_all self.data_records.destroy_all mode = :update elsif(mode == :update && files && self.data_records.size > 0) # On updating we should only remove the files if there are new ones self.data_records.destroy_all end # Add any files attach_files(files) if(files) # Rewrite the type, if neccessary type = properties[:type] switch_type = type && (self.type != type) # Warn to the log if we have a problematic type change TaliaCore.logger.warn("WARNING: Type change from #{self.type} to #{type}") if(switch_type && !self.is_a?(SourceTypes::DummySource)) self.type = type if(switch_type) # Now we should either be adding or updating assit(mode == :update || mode == :add) update = (mode == :update) # Overwrite with or add the imported attributes update ? rewrite_attributes(properties) : update_attributes(properties) self end |
#value_for(thing) ⇒ Object
Helper
79 80 81 |
# File 'lib/talia_core/active_source.rb', line 79 def value_for(thing) self.class.value_for(thing) end |
#write_predicate_direct(predicate, value) ⇒ Object
Writes the predicate directly to the database and the rdf store. The Source does not need to be saved and no data is loaded from the database. This is faster than adding the data normally and doing a full save, at least if only one or two predicates are written.
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 |
# File 'lib/talia_core/active_source.rb', line 303 def write_predicate_direct(predicate, value) autosave = self.autosave_rdf? value.save! if(value.is_a?(ActiveSource) && value.new_record?) self.autosave_rdf = false self[predicate] << value uri_res = N::URI.new(predicate) # Now add the RDF data by hand if(value.kind_of?(Array)) value.each do |v| my_rdf.direct_write_predicate(uri_res, v) end else my_rdf.direct_write_predicate(uri_res, value) end save! # Save without RDF save self.autosave_rdf = autosave end |