| Class | TaliaCore::SemanticCollectionWrapper |
| In: |
lib/talia_core/semantic_collection_wrapper.rb
|
| Parent: | Object |
Class for the collection of elements returned by the "semantic accessor" methods of a source (e.g. source)
Each wrapper contains the values for one predicate of one source (that is, for all triples of the form <thesource> <thepredicate> ?object).
The wrapper will lazy-load the data and only do a query to the database once the items are actually requested. If a database request is necessary, all data will be fetched in a single request.
Modifications of the wrapper will happen in memory. Only when the wrapper is saved using save_items! will the modifications be written to the data store. save_items! will be called by the "owning" source of this wrapper when the source is being saved.
Some of the methods work on the values, and other on the objects of the collection. See SemanticCollectionItem#value and SemanticCollectionItem#object for more on that.
| force_type | [R] |
Initialize the collection with the given source and predicate. No database will take place during creation of the object
# File lib/talia_core/semantic_collection_wrapper.rb, line 38
38: def initialize(source, predicate)
39: @assoc_source = source
40: @assoc_predicate = if(predicate.respond_to?(:uri))
41: predicate.uri.to_s
42: else
43: predicate.to_s
44: end
45: @force_type = self.class.special_types[@assoc_predicate]
46: end
Simple hash that checks if a type if property requires "special" handling This will cause the wrapper to accept ActiveSource relations and all sources will be casted to the given type
# File lib/talia_core/semantic_collection_wrapper.rb, line 30
30: def self.special_types
31: @special_types ||= {
32: N::RDF.type.to_s => N::SourceClass
33: }
34: end
Creates a record for a value and adds it. This will add the given value if it is a database record and otherwise create a property with the given value.
If a block is given, it will be called with the new element after the new element has been added to the collection. If value is a collection, the block will be called for each element of the collection.
The order, if not nil, can be used to have a fixed order of SemanticRelation records. This is mainly used by the Collection class
# File lib/talia_core/semantic_collection_wrapper.rb, line 161
161: def add_record(value, order = nil)
162: raise(ArgumentError, "Blank value assigned") if(value.blank? && !value.is_a?(Enumerable))
163: # We use order exclusively for "ordering" predicates
164: assit_equal(TaliaCore::Collection.index_to_predicate(order), @assoc_predicate) if(order)
165:
166: value = [ value ] unless(value.kind_of?(Array))
167:
168: value.each do |val|
169: rel = create_predicate(val)
170: rel.rel_order = order if(order)
171: block_given? ? yield(rel) : insert_item(rel)
172: end
173: end
Indicates that the wraper is "clean", that is it hasn‘t been written to or read from
# File lib/talia_core/semantic_collection_wrapper.rb, line 245
245: def clean?
246: @items.nil?
247: end
# File lib/talia_core/semantic_collection_wrapper.rb, line 249
249: def empty?
250: self.size == 0
251: end
Check if the collection includes the value given
# File lib/talia_core/semantic_collection_wrapper.rb, line 148
148: def include?(value)
149: items.include?(value)
150: end
Index of the given value
# File lib/talia_core/semantic_collection_wrapper.rb, line 143
143: def index(value)
144: items.index(value)
145: end
Forces this relation to be empty. This initializes the relation, assuming that no data exists in the database. The collection will be empty, and the database will not be queried.
Warning Only call this if you need an empty wrapper and you are sure that there are no corresponding values in the database
# File lib/talia_core/semantic_collection_wrapper.rb, line 259
259: def init_as_empty!
260: raise(ArgumentError, "Already initialized!") if(loaded?)
261: @items = []
262: @loaded = true
263: end
Indicates of the internal collection is loaded
# File lib/talia_core/semantic_collection_wrapper.rb, line 239
239: def loaded?
240: @loaded
241: end
Remove the given value. With no parameters, the whole list will be cleared and the RDF will be updated immediately (!).
# File lib/talia_core/semantic_collection_wrapper.rb, line 207
207: def remove(*params)
208: if(params.length > 0)
209: params.each { |par| remove_relation(par) }
210: else
211: if(loaded?)
212: items.each { |item| item.destroy }
213: else
214: SemanticRelation.destroy_all(
215: :subject_id => @assoc_source.id,
216: :predicate_uri => @assoc_predicate
217: )
218: end
219: @assoc_source.my_rdf.remove(@assoc_predicate.to_uri) unless(@assoc_source.uri.to_s.blank?)
220: @items = []
221: @loaded = true
222: end
223: end
Replace the contents of the current wrapper with the values passed. Blank values are ignored by this method. If non new values are passed (or all values are blank), this will simply
# File lib/talia_core/semantic_collection_wrapper.rb, line 189
189: def replace(*new_values)
190: new_values.flatten! if(new_values.first.is_a?(Array)) # Flatten if used as #replace([a, b, c])
191: new_values.reject! { |v| v.blank? }
192: new_values.collect! { |v| create_predicate(v) }
193: remaining_items = []
194: items.each do |item|
195: if(new_values.include?(item))
196: remaining_items << item
197: new_values.delete(item)
198: else
199: item.destroy
200: end
201: end
202: @items = remaining_items + new_values
203: end
Replace a value with a new one. Equivalent to removing the old value and adding the new one
# File lib/talia_core/semantic_collection_wrapper.rb, line 179
179: def replace_value(old_value, new_value)
180: idx = items.index(old_value)
181: items[idx].destroy
182: # Creates a new relation and adds it in the place of the old one
183: add_record(new_value) { |new_item| items[idx] = new_item }
184: end
This attempts to save the items to the database. This will do nothing if the collection was never loaded to memory. It also tries to ignore data that is known to already exist in the data store and only write the records could actually have been modified.
# File lib/talia_core/semantic_collection_wrapper.rb, line 229
229: def save_items!
230: return if(clean?) # If there are no items, nothing was modified
231: @assoc_source.save! unless(@assoc_source.id)
232: @items.each do |item|
233: item.save!
234: end
235: @items = nil unless(loaded?) # Otherwise we'll have trouble reload-and merging
236: end
Size of the collection
# File lib/talia_core/semantic_collection_wrapper.rb, line 123
123: def size
124: return items.size if(loaded?)
125: if(@items)
126: # This is not really possible without loading, so we do it
127: load!
128: items.size
129: else
130: SemanticRelation.count(:conditions => {
131: 'subject_id' => @assoc_source.id,
132: 'predicate_uri' => @assoc_predicate })
133: end
134: end
Returns only the values of the given language. (At the moment this is not aware of region codes or any specialities, it just does a string matching)
If no values with the given locale are found, this will fall back on the default locale and then to the values that don‘t have a locale at all.
# File lib/talia_core/semantic_collection_wrapper.rb, line 101
101: def values_with_lang(language = 'en')
102: language_is_default = (language == I18n.default_locale.to_s)
103: real = []
104: default = []
105: unset = []
106: items.each do |item|
107: # FIXME: At the moment, this only works for value attributes, not for
108: # sources
109: if((val = item.value).respond_to?(:lang))
110: real << val if(val.lang == language)
111: default << val if(!language_is_default && (val.lang == I18n.default_locale.to_s))
112: unset << val if(val.lang.blank?)
113: else
114: default << val
115: end
116: end
117: return real unless(real.empty?)
118: return default unless(default.empty?)
119: unset
120: end