active-triples 0.2.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a31ce4cccede2e3befa05a4b20dc4894547b219a
4
- data.tar.gz: 8c47c1b2ad7a9514298dbae6f290c09313590c6d
3
+ metadata.gz: 6fe9b5e7c31b1ebd51f2c529d354c27ff5a50461
4
+ data.tar.gz: 96039e8d7e41040748705955d064101fce40f236
5
5
  SHA512:
6
- metadata.gz: dea13110704ca324e2cce448cd413450e21c0a6837ea269f7be8aa783b5540f85d9a11df04a2a891c1986ed40eb551347b06119547518c7e43c093cc715504c8
7
- data.tar.gz: 82fbe1c1025d727d396eb8e3c612b56b209d40bac4bec074cef008afa91c052a58e7b344a38a47b29943d725f273776c83b04070a403abcf53adbdf3a6682372
6
+ metadata.gz: 6c2474afde1a6b48790bed08a67caf0e413f8339cfa5993f0ef6bcb277cf642c21bc5d0f2e1ce830f735766d704ca35cd6bacc3076a1645d52f96f28ba44cd7a
7
+ data.tar.gz: abbe7fd8978112727f975413aa4cb5bb9a20cfc443c4e2f128d4469010391f20bc79e3466575e68153413b1db7763c7be1aa7f633ed6c75796e3213ac460af37
@@ -1,16 +1,22 @@
1
1
  require 'rdf'
2
2
  require 'active_triples/version'
3
+ require 'active_support'
3
4
 
4
5
  module ActiveTriples
5
- autoload :Resource, 'active_triples/resource'
6
- autoload :List, 'active_triples/list'
7
- autoload :Term, 'active_triples/term'
8
- autoload :Indexing, 'active_triples/indexing'
9
- autoload :Configurable, 'active_triples/configurable'
10
- autoload :Properties, 'active_triples/properties'
11
- autoload :Repositories, 'active_triples/repositories'
12
- autoload :NodeConfig, 'active_triples/node_config'
13
- autoload :NestedAttributes, 'active_triples/nested_attributes'
6
+ extend ActiveSupport::Autoload
7
+ eager_autoload do
8
+ autoload :Resource
9
+ autoload :List
10
+ autoload :Term
11
+ autoload :Indexing
12
+ autoload :Configurable
13
+ autoload :Properties
14
+ autoload :PropertyBuilder
15
+ autoload :Reflection
16
+ autoload :Repositories
17
+ autoload :NodeConfig
18
+ autoload :NestedAttributes
19
+ end
14
20
 
15
21
  def self.class_from_string(class_name, container_class=Kernel)
16
22
  container_class = container_class.name if container_class.is_a? Module
@@ -8,7 +8,8 @@ module ActiveTriples
8
8
  class List < RDF::List
9
9
  include ActiveTriples::NestedAttributes
10
10
  extend Configurable
11
- extend Properties
11
+ include Properties
12
+ include Reflection
12
13
 
13
14
  delegate :rdf_subject, :mark_for_destruction, :marked_for_destruction?, :set_value, :get_values, :parent, :type, :dump, :attributes=, to: :resource
14
15
  alias_method :to_ary, :to_a
@@ -30,10 +31,6 @@ module ActiveTriples
30
31
  @graph = ListResource.new(subject) << graph unless graph.kind_of? Resource
31
32
  graph << parent if parent
32
33
  graph.list = self
33
- graph.singleton_class.properties = self.class.properties
34
- graph.singleton_class.properties.keys.each do |property|
35
- graph.singleton_class.send(:register_property, property)
36
- end
37
34
  graph.reload
38
35
  end
39
36
 
@@ -107,11 +104,15 @@ module ActiveTriples
107
104
  @list ||= list
108
105
  end
109
106
 
107
+ def reflections
108
+ @list.class
109
+ end
110
+
110
111
  def attributes=(values)
111
112
  raise ArgumentError, "values must be a Hash, you provided #{values.class}" unless values.kind_of? Hash
112
113
  values.with_indifferent_access.each do |key, value|
113
- if self.singleton_class.properties.keys.map{ |k| "#{k}_attributes"}.include?(key)
114
- klass = properties[key[0..-12]]['class_name']
114
+ if reflections.properties.keys.map { |k| "#{k}_attributes" }.include?(key)
115
+ klass = reflections.reflect_on_property(key[0..-12])['class_name']
115
116
  klass = ActiveTriples.class_from_string(klass, final_parent.class) if klass.is_a? String
116
117
  value.is_a?(Hash) ? attributes_hash_to_list(values[key], klass) : attributes_to_list(value, klass)
117
118
  values.delete key
@@ -159,9 +160,9 @@ module ActiveTriples
159
160
  when Array then RDF::List.new(nil, graph, value)
160
161
  else value
161
162
  end
162
-
163
+
163
164
  if subject == RDF.nil
164
- @subject = RDF::Node.new
165
+ @subject = RDF::Node.new
165
166
  @graph = ListResource.new(subject)
166
167
  @graph.type = RDF.List
167
168
  end
@@ -50,7 +50,7 @@ module ActiveTriples
50
50
 
51
51
  attributes_collection.each do |attributes|
52
52
  attributes = attributes.with_indifferent_access
53
-
53
+
54
54
  if attributes['id'] && existing_record = association.detect { |record| record.rdf_subject.to_s == attributes['id'].to_s }
55
55
  if !call_reject_if(association_name, attributes)
56
56
  assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
@@ -83,7 +83,7 @@ module ActiveTriples
83
83
  def has_destroy_flag?(hash)
84
84
  ["1", "true"].include?(hash['_destroy'].to_s)
85
85
  end
86
-
86
+
87
87
  module ClassMethods
88
88
  def accepts_nested_attributes_for *attr_names
89
89
  options = { :allow_destroy => false, :update_only => false }
@@ -6,8 +6,9 @@ module ActiveTriples
6
6
  self.term = term
7
7
  self.predicate = predicate
8
8
  self.class_name = args.delete(:class_name)
9
- self.multivalue = args.delete(:multivalue) { true }
9
+ self.multivalue = args.delete(:multivalue) { true }
10
10
  raise ArgumentError, "Invalid arguments for Rdf Node configuration: #{args} on #{predicate}" unless args.empty?
11
+ yield(self) if block_given?
11
12
  end
12
13
 
13
14
  def [](value)
@@ -11,73 +11,59 @@ module ActiveTriples
11
11
  # property :title, predicate: RDF::DC.title, class_name: ResourceClass
12
12
  #
13
13
  module Properties
14
- attr_accessor :config
14
+ extend ActiveSupport::Concern
15
15
 
16
- ##
17
- # Registers properties for Resource-like classes
18
- # @param [Symbol] name of the property (and its accessor methods)
19
- # @param [Hash] opts for this property, must include a :predicate
20
- # @yield [index] index sets solr behaviors for the property
21
- def property(name, opts={}, &block)
22
- self.config[name] = NodeConfig.new(name, opts[:predicate], opts.except(:predicate)).tap do |config|
23
- config.with_index(&block) if block_given?
24
- end
25
- behaviors = config[name].behaviors.flatten if config[name].behaviors and not config[name].behaviors.empty?
26
- register_property(name)
16
+ included do
17
+ initialize_generated_modules
27
18
  end
28
19
 
29
- ##
30
- # Returns the properties registered to the class and their
31
- # configurations.
32
- #
33
- # @return [ActiveSupport::HashWithIndifferentAccess{String => ActiveTriples::NodeConfig}]
34
- def config
35
- @config ||= if superclass.respond_to? :config
36
- superclass.config.dup
37
- else
38
- {}.with_indifferent_access
20
+ module ClassMethods
21
+ def inherited(child_class) #:nodoc:
22
+ child_class.initialize_generated_modules
23
+ super
39
24
  end
40
- end
41
-
42
- alias_method :properties, :config
43
- alias_method :properties=, :config=
44
25
 
45
- ##
46
- # Given a property name or a predicate, return the configuration
47
- # for the matching property.
48
- #
49
- # @param term [#to_sym, RDF::Resource] a property name to predicate
50
- #
51
- # @return [ActiveTriples::NodeConfig]
52
- def config_for_term_or_uri(term)
53
- return config[term.to_sym] unless term.kind_of? RDF::Resource
54
- config.each { |k, v| return v if v.predicate == term.to_uri }
55
- end
26
+ def initialize_generated_modules # :nodoc:
27
+ generated_property_methods
28
+ end
56
29
 
57
- ##
58
- # List the property names registered to the class.
59
- #
60
- # @return [Array<Symbol>] list of the symbolized names of registered
61
- # properties
62
- def fields
63
- properties.keys.map(&:to_sym)
64
- end
30
+ def generated_property_methods
31
+ @generated_property_methods ||= begin
32
+ mod = const_set(:GeneratedPropertyMethods, Module.new)
33
+ include mod
34
+ mod
35
+ end
36
+ end
65
37
 
66
- private
38
+ ##
39
+ # Registers properties for Resource-like classes
40
+ # @param [Symbol] name of the property (and its accessor methods)
41
+ # @param [Hash] opts for this property, must include a :predicate
42
+ # @yield [index] index sets solr behaviors for the property
43
+ def property(name, opts={}, &block)
44
+ reflection = PropertyBuilder.build(self, name, opts, &block)
45
+ Reflection.add_reflection self, name, reflection
46
+ end
67
47
 
68
- ##
69
- # Private method for creating accessors for a given property.
70
- #
71
- # @param [#to_s] name Name of the accessor to be created,
72
- # get/set_value is called on the resource using this.
73
- def register_property(name)
74
- parent = Proc.new{self}
75
- # parent = Proc.new{resource} if self < ActiveFedora::Datastream
76
- define_method "#{name}=" do |*args|
77
- instance_eval(&parent).set_value(name.to_sym, *args)
48
+ ##
49
+ # Given a property name or a predicate, return the configuration
50
+ # for the matching property.
51
+ #
52
+ # @param term [#to_sym, RDF::Resource] a property name to predicate
53
+ #
54
+ # @return [ActiveTriples::NodeConfig]
55
+ def config_for_term_or_uri(term)
56
+ return config[term.to_sym] unless term.kind_of? RDF::Resource
57
+ config.each_value { |v| return v if v.predicate == term.to_uri }
78
58
  end
79
- define_method name do
80
- instance_eval(&parent).get_values(name.to_sym)
59
+
60
+ ##
61
+ # List the property names registered to the class.
62
+ #
63
+ # @return [Array<Symbol>] list of the symbolized names of registered
64
+ # properties
65
+ def fields
66
+ properties.keys.map(&:to_sym)
81
67
  end
82
68
  end
83
69
  end
@@ -0,0 +1,53 @@
1
+ module ActiveTriples
2
+ class PropertyBuilder
3
+
4
+ attr_reader :name, :options
5
+
6
+ def initialize(name, options, &block)
7
+ @name = name
8
+ @options = options
9
+ end
10
+
11
+ def self.create_builder(name, options, &block)
12
+ raise ArgumentError, "property names must be a Symbol" unless name.kind_of?(Symbol)
13
+
14
+ new(name, options, &block)
15
+ end
16
+
17
+ def self.build(model, name, options, &block)
18
+ builder = create_builder name, options, &block
19
+ reflection = builder.build(&block)
20
+ define_accessors model, reflection
21
+ reflection
22
+ end
23
+
24
+ def self.define_accessors(model, reflection)
25
+ mixin = model.generated_property_methods
26
+ name = reflection.term
27
+ define_readers(mixin, name)
28
+ define_writers(mixin, name)
29
+ end
30
+
31
+ def self.define_readers(mixin, name)
32
+ mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
33
+ def #{name}(*args)
34
+ get_values(:#{name})
35
+ end
36
+ CODE
37
+ end
38
+
39
+ def self.define_writers(mixin, name)
40
+ mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
41
+ def #{name}=(value)
42
+ set_value(:#{name}, value)
43
+ end
44
+ CODE
45
+ end
46
+
47
+ def build(&block)
48
+ NodeConfig.new(name, options[:predicate], options.except(:predicate)) do |config|
49
+ config.with_index(&block) if block_given?
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,30 @@
1
+ require 'active_support/core_ext/class'
2
+
3
+ module ActiveTriples
4
+ module Reflection
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ class_attribute :_active_triples_config
9
+ self._active_triples_config = {}
10
+ end
11
+
12
+ def self.add_reflection(model, name, reflection)
13
+ model._active_triples_config = model._active_triples_config.merge(name.to_s => reflection)
14
+ end
15
+
16
+ module ClassMethods
17
+ def reflect_on_property(term)
18
+ _active_triples_config[term.to_s]
19
+ end
20
+
21
+ def properties
22
+ _active_triples_config
23
+ end
24
+
25
+ def properties=(val)
26
+ self._active_triples_config = val
27
+ end
28
+ end
29
+ end
30
+ end
@@ -22,7 +22,7 @@ module ActiveTriples
22
22
  class Resource < RDF::Graph
23
23
  @@type_registry
24
24
  extend Configurable
25
- extend Properties
25
+ include Properties
26
26
  extend Deprecation
27
27
  extend ActiveModel::Naming
28
28
  extend ActiveModel::Translation
@@ -31,6 +31,7 @@ module ActiveTriples
31
31
  include ActiveModel::Serialization
32
32
  include ActiveModel::Serializers::JSON
33
33
  include NestedAttributes
34
+ include Reflection
34
35
  attr_accessor :parent
35
36
 
36
37
  class << self
@@ -116,14 +117,18 @@ module ActiveTriples
116
117
  hash
117
118
  end
118
119
 
120
+ def reflections
121
+ self.class
122
+ end
123
+
119
124
  def attributes=(values)
120
125
  raise ArgumentError, "values must be a Hash, you provided #{values.class}" unless values.kind_of? Hash
121
126
  values = values.with_indifferent_access
122
127
  set_subject!(values.delete(:id)) if values.has_key?(:id) and node?
123
128
  values.each do |key, value|
124
- if properties.keys.include?(key)
129
+ if reflections.reflect_on_property(key)
125
130
  set_value(rdf_subject, key, value)
126
- elsif self.singleton_class.nested_attributes_options.keys.map{ |k| "#{k}_attributes"}.include?(key)
131
+ elsif nested_attributes_options.keys.map { |k| "#{k}_attributes" }.include?(key)
127
132
  send("#{key}=".to_sym, value)
128
133
  else
129
134
  raise ArgumentError, "No association found for name `#{key}'. Has it been defined yet?"
@@ -143,7 +148,7 @@ module ActiveTriples
143
148
  # @return [String]
144
149
  def dump(*args)
145
150
  if args.first == :jsonld and respond_to?(:jsonld_context)
146
- args << {} unless args.last.is_a?(Hash)
151
+ args << {} unless args.last.is_a?(Hash)
147
152
  args.last[:context] ||= jsonld_context
148
153
  end
149
154
  super
@@ -206,16 +211,16 @@ module ActiveTriples
206
211
  end
207
212
 
208
213
  ##
209
- # Load data from the #rdf_subject URI. Retrieved data will be
214
+ # Load data from the #rdf_subject URI. Retrieved data will be
210
215
  # parsed into the Resource's graph from available RDF::Readers
211
- # and available from property accessors if if predicates are
216
+ # and available from property accessors if if predicates are
212
217
  # registered.
213
- #
218
+ #
214
219
  # osu = ActiveTriples::Resource.new('http://dbpedia.org/resource/Oregon_State_University')
215
220
  # osu.fetch
216
221
  # osu.rdf_label.first
217
222
  # # => "Oregon State University"
218
- #
223
+ #
219
224
  # @return [ActiveTriples::Resource] self
220
225
  def fetch
221
226
  load(rdf_subject)
@@ -405,23 +410,23 @@ module ActiveTriples
405
410
  end
406
411
 
407
412
  private
408
-
413
+
409
414
  ##
410
415
  # Returns the properties registered and their configurations.
411
416
  #
412
417
  # @return [ActiveSupport::HashWithIndifferentAccess{String => ActiveTriples::NodeConfig}]
413
418
  def properties
414
- self.singleton_class.properties
419
+ _active_triples_config
415
420
  end
416
421
 
417
422
  ##
418
423
  # List of RDF predicates registered as properties on the object.
419
424
  #
420
425
  # @return [Array<RDF::URI>]
421
- def registered_predicates
426
+ def registered_predicates
422
427
  properties.values.map { |config| config.predicate }
423
428
  end
424
-
429
+
425
430
  ##
426
431
  # List of RDF predicates used in the Resource's triples, but not
427
432
  # mapped to any property or accessor methods.
@@ -434,12 +439,12 @@ module ActiveTriples
434
439
  end
435
440
 
436
441
  ##
437
- # Given a predicate which has been registered to a property,
442
+ # Given a predicate which has been registered to a property,
438
443
  # returns the name of the matching property.
439
444
  #
440
445
  # @param predicate [RDF::URI]
441
446
  #
442
- # @return [String, nil] the name of the property mapped to the
447
+ # @return [String, nil] the name of the property mapped to the
443
448
  # predicate provided
444
449
  def property_for_predicate(predicate)
445
450
  properties.each do |property, values|
@@ -463,7 +468,7 @@ module ActiveTriples
463
468
  # @return [RDF::Repository, ActiveTriples::Resource] the target
464
469
  # repository
465
470
  def repository
466
- @repository ||=
471
+ @repository ||=
467
472
  if self.class.repository == :parent
468
473
  final_parent
469
474
  else
@@ -476,16 +481,16 @@ module ActiveTriples
476
481
  # an RDF term. If a String is given, first tries to interpret it
477
482
  # as a valid URI, then tries to append it to base_uri. Finally,
478
483
  # raises an error if no valid term can be built.
479
- #
484
+ #
480
485
  # The argument must be an RDF::Node, an object that responds to
481
486
  # #to_uri, a String that represents a valid URI, or a String that
482
487
  # appends to the Resource's base_uri to create a valid URI.
483
488
  #
484
- # @TODO: URI.scheme_list is naive and incomplete. Find a better
489
+ # @TODO: URI.scheme_list is naive and incomplete. Find a better
485
490
  # way to check for an existing scheme.
486
491
  #
487
492
  # @param uri_or_str [RDF::Resource, String]
488
- #
493
+ #
489
494
  # @return [RDF::Resource] A term
490
495
  # @raise [RuntimeError] no valid RDF term could be built
491
496
  def get_uri(uri_or_str)
@@ -4,11 +4,13 @@ module ActiveTriples
4
4
  class Term
5
5
 
6
6
  attr_accessor :parent, :value_arguments, :node_cache
7
+ attr_reader :reflections
7
8
 
8
9
  delegate *(Array.public_instance_methods - [:send, :__send__, :__id__, :class, :object_id] + [:as_json]), :to => :result
9
10
 
10
- def initialize(parent, value_arguments)
11
- self.parent = parent
11
+ def initialize(parent_resource, value_arguments)
12
+ self.parent = parent_resource
13
+ @reflections = parent_resource.reflections
12
14
  self.value_arguments = value_arguments
13
15
  end
14
16
 
@@ -18,8 +20,10 @@ module ActiveTriples
18
20
 
19
21
  def result
20
22
  result = parent.query(:subject => rdf_subject, :predicate => predicate)
21
- .map{|x| convert_object(x.object)}
22
- .reject(&:nil?)
23
+ .each_with_object([]) do |x, collector|
24
+ converted_object = convert_object(x.object)
25
+ collector << converted_object unless converted_object.nil?
26
+ end
23
27
  return result if !property_config || property_config[:multivalue]
24
28
  result.first
25
29
  end
@@ -42,9 +46,9 @@ module ActiveTriples
42
46
  end
43
47
 
44
48
  def build(attributes={})
45
- new_subject = attributes.key?('id') ? attributes.delete('id') : RDF::Node.new
49
+ new_subject = attributes.fetch('id') { RDF::Node.new }
46
50
  make_node(new_subject).tap do |node|
47
- node.attributes = attributes
51
+ node.attributes = attributes.except('id')
48
52
  if parent.kind_of? List::ListResource
49
53
  parent.list << node
50
54
  elsif node.kind_of? RDF::List
@@ -73,8 +77,8 @@ module ActiveTriples
73
77
  alias_method :push, :<<
74
78
 
75
79
  def property_config
76
- return type_property if (property == RDF.type || property.to_s == "type") && !parent.send(:properties)[property]
77
- parent.send(:properties)[property]
80
+ return type_property if (property == RDF.type || property.to_s == "type") && (!reflections.kind_of?(Resource) || !reflections.reflect_on_property(property))
81
+ reflections.reflect_on_property(property)
78
82
  end
79
83
 
80
84
  def type_property
@@ -113,7 +117,7 @@ module ActiveTriples
113
117
  return
114
118
  end
115
119
  val = val.to_uri if val.respond_to? :to_uri
116
- raise 'value must be an RDF URI, Node, Literal, or a valid datatype. See RDF::Literal' unless
120
+ raise "value must be an RDF URI, Node, Literal, or a valid datatype. See RDF::Literal.\n\tYou provided #{val.inspect}" unless
117
121
  val.kind_of? RDF::Value or val.kind_of? RDF::Literal
118
122
  parent.insert [rdf_subject, predicate, val]
119
123
  end
@@ -144,7 +148,7 @@ module ActiveTriples
144
148
  def convert_object(value)
145
149
  case value
146
150
  when RDF::Literal
147
- value.object
151
+ value.object
148
152
  when RDF::Resource
149
153
  make_node(value)
150
154
  else
@@ -1,3 +1,3 @@
1
1
  module ActiveTriples
2
- VERSION = "0.2.3"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -29,7 +29,8 @@ describe ActiveTriples::Configurable do
29
29
 
30
30
  describe '#rdf_type' do
31
31
  it "should set the type the old way" do
32
- DummyConfigurable.should_receive(:configure).with(type: RDF::RDFS.Class).and_call_original
32
+ expect(DummyConfigurable).to receive(:configure).with(type: RDF::RDFS.Class).and_call_original
33
+ expect(Deprecation).to receive(:warn)
33
34
  DummyConfigurable.rdf_type(RDF::RDFS.Class)
34
35
  expect(DummyConfigurable.type).to eq RDF::RDFS.Class
35
36
  end
@@ -5,7 +5,7 @@ require 'linkeddata'
5
5
  describe ActiveTriples::List do
6
6
 
7
7
  subject { ActiveTriples::List.new }
8
-
8
+
9
9
  context 'when empty' do
10
10
  it 'has subject of RDF.nil' do
11
11
  expect(subject.subject).to eq RDF.nil
@@ -43,7 +43,7 @@ describe ActiveTriples::List do
43
43
  it 'has correct number of elements' do
44
44
  expect(subject.length).to eq 3
45
45
  end
46
-
46
+
47
47
  context 'after clear' do
48
48
  before do
49
49
  subject.clear
@@ -247,7 +247,7 @@ END
247
247
  expect(doc.xpath('//mads:ComplexSubject/mads:elementList/*[position() = 2]/mads:elementValue', ns).map(&:text)).to eq ["Relations with Mexican Americans"]
248
248
  expect(doc.xpath('//mads:ComplexSubject/mads:elementList/*[position() = 3]/@rdf:about', ns).map(&:value)).to eq ["http://library.ucsd.edu/ark:/20775/bbXXXXXXX4"]
249
249
  expect(doc.xpath('//mads:ComplexSubject/mads:elementList/*[position() = 4]/mads:elementValue', ns).map(&:text)).to eq ["1900s"]
250
- expect(RDF::List.new(list.rdf_subject, subject.graph)).to be_valid
250
+ expect(RDF::List.new(list.rdf_subject, subject)).to be_valid
251
251
  end
252
252
 
253
253
  it "should be a valid list" do
@@ -255,9 +255,9 @@ END
255
255
  # TODO this is a workaround for https://github.com/projecthydra/active_fedora/issues/444
256
256
  # remove the following line when #444 is closed.
257
257
  list.resource.persist!
258
- expect(RDF::List.new(list.rdf_subject, subject.graph)).to be_valid
258
+ expect(RDF::List.new(list.rdf_subject, subject)).to be_valid
259
259
  end
260
- end
260
+ end
261
261
  end
262
262
  end
263
263
  end
@@ -85,7 +85,7 @@ describe "nesting attribute behavior" do
85
85
  personalName_attributes: [
86
86
  {
87
87
  id: 'http://library.ucsd.edu/ark:20775/jefferson',
88
- elementList_attributes: [{
88
+ elementList_attributes: [{
89
89
  fullNameElement: "Jefferson, Thomas",
90
90
  dateNameElement: "1743-1826"
91
91
  }]
@@ -123,12 +123,12 @@ describe "nesting attribute behavior" do
123
123
  expect(subject.personalName.first.elementList.first.fullNameElement).to eq ["Jefferson, Thomas"]
124
124
  expect(subject.personalName.first.elementList.first.dateNameElement).to eq ["1743-1826"]
125
125
  end
126
-
126
+
127
127
  it 'should build nodes with ids' do
128
128
  expect(subject.topic[0].elementList.first[0].rdf_subject).to eq 'http://library.ucsd.edu/ark:/20775/bb3333333x'
129
129
  expect(subject.personalName.first.rdf_subject).to eq 'http://library.ucsd.edu/ark:20775/jefferson'
130
130
  end
131
-
131
+
132
132
  it 'should fail when writing to a non-predicate' do
133
133
  attributes = { topic_attributes: { '0' => { elementList_attributes: [{ topicElement_attributes: [{ fake_predicate:"Cosmology" }] }]}}}
134
134
  expect{ subject.attributes = attributes }.to raise_error ArgumentError
@@ -2,7 +2,8 @@ require "spec_helper"
2
2
  describe ActiveTriples::Properties do
3
3
  before do
4
4
  class DummyProperties
5
- extend ActiveTriples::Properties
5
+ include ActiveTriples::Reflection
6
+ include ActiveTriples::Properties
6
7
  end
7
8
  end
8
9
 
@@ -13,29 +14,29 @@ describe ActiveTriples::Properties do
13
14
  describe '#property' do
14
15
  it 'should set a property' do
15
16
  DummyProperties.property :title, :predicate => RDF::DC.title
16
- expect(DummyProperties.properties).to include :title
17
+ expect(DummyProperties.reflect_on_property(:title)).to be_kind_of ActiveTriples::NodeConfig
17
18
  end
18
19
 
19
20
  it 'should set index behaviors' do
20
21
  DummyProperties.property :title, :predicate => RDF::DC.title do |index|
21
22
  index.as :facetable, :searchable
22
23
  end
23
- expect(DummyProperties.properties[:title][:behaviors]).to eq [:facetable, :searchable]
24
+ expect(DummyProperties.reflect_on_property(:title)[:behaviors]).to eq [:facetable, :searchable]
24
25
  end
25
26
 
26
27
  it 'should set class name' do
27
28
  DummyProperties.property :title, :predicate => RDF::DC.title, :class_name => RDF::Literal
28
- expect(DummyProperties.properties[:title][:class_name]).to eq RDF::Literal
29
+ expect(DummyProperties.reflect_on_property(:title)[:class_name]).to eq RDF::Literal
29
30
  end
30
31
 
31
32
  it "should constantize string class names" do
32
33
  DummyProperties.property :title, :predicate => RDF::DC.title, :class_name => "RDF::Literal"
33
- expect(DummyProperties.properties[:title][:class_name]).to eq RDF::Literal
34
+ expect(DummyProperties.reflect_on_property(:title)[:class_name]).to eq RDF::Literal
34
35
  end
35
36
 
36
37
  it "should keep strings which it can't constantize as strings" do
37
38
  DummyProperties.property :title, :predicate => RDF::DC.title, :class_name => "FakeClassName"
38
- expect(DummyProperties.properties[:title][:class_name]).to eq "FakeClassName"
39
+ expect(DummyProperties.reflect_on_property(:title)[:class_name]).to eq "FakeClassName"
39
40
  end
40
41
  end
41
42
 
@@ -52,7 +53,8 @@ describe ActiveTriples::Properties do
52
53
  end
53
54
 
54
55
  it 'should carry properties from superclass' do
55
- expect(DummySubClass.properties.keys).to eq ["title", "source"]
56
+ expect(DummySubClass.reflect_on_property(:title)).to be_kind_of ActiveTriples::NodeConfig
57
+ expect(DummySubClass.reflect_on_property(:source)).to be_kind_of ActiveTriples::NodeConfig
56
58
  end
57
59
  end
58
60
  end
@@ -202,7 +202,7 @@ describe ActiveTriples::Resource do
202
202
  end
203
203
  end
204
204
  end
205
-
205
+
206
206
  describe 'class_name' do
207
207
  it 'should raise an error when not a class or string' do
208
208
  DummyResource.property :relation, :predicate => RDF::DC.relation, :class_name => RDF::URI('http://example.org')
@@ -210,14 +210,33 @@ describe ActiveTriples::Resource do
210
210
  d.relation = RDF::DC.type
211
211
  expect { d.relation.first }.to raise_error "class_name for relation is a RDF::URI; must be a class"
212
212
  end
213
-
213
+
214
214
  it 'should return nil when none is given' do
215
- expect(DummyResource.properties['title'][:class_name]).to be_nil
215
+ expect(DummyResource.reflect_on_property('title')[:class_name]).to be_nil
216
216
  end
217
+
217
218
  end
218
-
219
+
220
+ context 'property configuration' do
221
+ it 'preserves previous #properties[] API but prefers #reflect_on_property' do
222
+ expect(DummyResource.reflect_on_property('title')).to eq(DummyResource.properties.fetch('title'))
223
+ end
224
+
225
+ it 'uses hash access on #properties to retrieve the configuration' do
226
+ expect(DummyResource.properties['title']).to be_a(ActiveTriples::NodeConfig)
227
+ end
228
+
229
+ it 'stores the properties configuration as a hash' do
230
+ expect(DummyResource.properties).to be_a(Hash)
231
+ end
232
+
233
+ it "uses reflection to retrieve a property's configuration" do
234
+ expect(DummyResource.reflect_on_property('title')).to be_a(ActiveTriples::NodeConfig)
235
+ end
236
+ end
237
+
219
238
  describe 'attributes' do
220
- before do
239
+ before do
221
240
  subject.license = license
222
241
  subject.title = 'moomi'
223
242
  end
@@ -4,7 +4,10 @@ require 'rdf/isomorphic'
4
4
  describe ActiveTriples::Term do
5
5
 
6
6
  describe "#rdf_subject" do
7
- subject { described_class.new( double("parent"), double("value args") ) }
7
+ let(:parent_resource) { double("parent resource", reflections: {}) }
8
+
9
+ subject { described_class.new(parent_resource, double("value args") ) }
10
+
8
11
  context "when term has 0 value arguments" do
9
12
  before { subject.value_arguments = double(length: 0) }
10
13
  it "should raise an error" do
@@ -35,7 +38,7 @@ describe ActiveTriples::Term do
35
38
  end
36
39
 
37
40
  describe "#valid_datatype?" do
38
- subject { described_class.new( double("parent"), "value" ) }
41
+ subject { described_class.new(double("parent", reflections: []), "value" ) }
39
42
  before { allow(subject.parent).to receive(:rdf_subject) { "parent subject" } }
40
43
  context "the value is not a Resource" do
41
44
  it "should be true if value is a String" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active-triples
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Johnson
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-08-22 00:00:00.000000000 Z
12
+ date: 2014-10-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rdf
@@ -189,6 +189,8 @@ files:
189
189
  - lib/active_triples/nested_attributes.rb
190
190
  - lib/active_triples/node_config.rb
191
191
  - lib/active_triples/properties.rb
192
+ - lib/active_triples/property_builder.rb
193
+ - lib/active_triples/reflection.rb
192
194
  - lib/active_triples/repositories.rb
193
195
  - lib/active_triples/resource.rb
194
196
  - lib/active_triples/term.rb