active-fedora 6.8.0 → 7.0.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +15 -5
- data/CONTRIBUTING.md +2 -0
- data/Gemfile +0 -2
- data/History.txt +2 -32
- data/README.md +143 -0
- data/Rakefile +5 -7
- data/active-fedora.gemspec +9 -9
- data/gemfiles/rails3.gemfile +11 -0
- data/gemfiles/rails4.gemfile +10 -0
- data/lib/active_fedora.rb +31 -4
- data/lib/active_fedora/association_relation.rb +18 -0
- data/lib/active_fedora/associations.rb +38 -171
- data/lib/active_fedora/associations/association.rb +163 -0
- data/lib/active_fedora/associations/association_scope.rb +39 -0
- data/lib/active_fedora/associations/belongs_to_association.rb +47 -25
- data/lib/active_fedora/associations/builder/association.rb +55 -0
- data/lib/active_fedora/associations/builder/belongs_to.rb +100 -0
- data/lib/active_fedora/associations/builder/collection_association.rb +56 -0
- data/lib/active_fedora/associations/builder/has_and_belongs_to_many.rb +30 -0
- data/lib/active_fedora/associations/builder/has_many.rb +63 -0
- data/lib/active_fedora/associations/builder/singular_association.rb +32 -0
- data/lib/active_fedora/associations/{association_collection.rb → collection_association.rb} +203 -53
- data/lib/active_fedora/associations/collection_proxy.rb +862 -0
- data/lib/active_fedora/associations/has_and_belongs_to_many_association.rb +35 -25
- data/lib/active_fedora/associations/has_many_association.rb +36 -11
- data/lib/active_fedora/associations/singular_association.rb +62 -0
- data/lib/active_fedora/attributes.rb +43 -139
- data/lib/active_fedora/autosave_association.rb +317 -0
- data/lib/active_fedora/base.rb +10 -327
- data/lib/active_fedora/callbacks.rb +1 -3
- data/lib/active_fedora/content_model.rb +16 -0
- data/lib/active_fedora/core.rb +151 -0
- data/lib/active_fedora/datastream_attribute.rb +76 -0
- data/lib/active_fedora/datastream_hash.rb +8 -13
- data/lib/active_fedora/datastreams.rb +39 -26
- data/lib/active_fedora/digital_object.rb +2 -2
- data/lib/active_fedora/fedora_attributes.rb +45 -0
- data/lib/active_fedora/fixture_loader.rb +1 -1
- data/lib/active_fedora/indexing.rb +6 -1
- data/lib/active_fedora/model.rb +0 -17
- data/lib/active_fedora/nested_attributes.rb +2 -2
- data/lib/active_fedora/null_relation.rb +7 -0
- data/lib/active_fedora/om_datastream.rb +3 -4
- data/lib/active_fedora/persistence.rb +41 -29
- data/lib/active_fedora/querying.rb +2 -163
- data/lib/active_fedora/rdf.rb +1 -0
- data/lib/active_fedora/rdf/indexing.rb +67 -0
- data/lib/active_fedora/rdf_datastream.rb +2 -50
- data/lib/active_fedora/rdf_node.rb +12 -7
- data/lib/active_fedora/rdf_node/term_proxy.rb +30 -21
- data/lib/active_fedora/rdfxml_rdf_datastream.rb +1 -1
- data/lib/active_fedora/reflection.rb +163 -20
- data/lib/active_fedora/relation.rb +33 -130
- data/lib/active_fedora/relation/calculations.rb +19 -0
- data/lib/active_fedora/relation/delegation.rb +22 -0
- data/lib/active_fedora/relation/finder_methods.rb +247 -0
- data/lib/active_fedora/relation/merger.rb +22 -0
- data/lib/active_fedora/relation/query_methods.rb +58 -0
- data/lib/active_fedora/relation/spawn_methods.rb +46 -0
- data/lib/active_fedora/relationship_graph.rb +0 -2
- data/lib/active_fedora/rels_ext_datastream.rb +1 -4
- data/lib/active_fedora/rubydora_connection.rb +1 -1
- data/lib/active_fedora/scoping.rb +20 -0
- data/lib/active_fedora/scoping/default.rb +38 -0
- data/lib/active_fedora/scoping/named.rb +32 -0
- data/lib/active_fedora/semantic_node.rb +54 -106
- data/lib/active_fedora/serialization.rb +19 -0
- data/lib/active_fedora/sharding.rb +58 -0
- data/lib/active_fedora/solr_digital_object.rb +15 -5
- data/lib/active_fedora/solr_instance_loader.rb +1 -1
- data/lib/active_fedora/solr_service.rb +1 -1
- data/lib/active_fedora/unsaved_digital_object.rb +6 -4
- data/lib/active_fedora/version.rb +1 -1
- data/lib/tasks/active_fedora.rake +3 -0
- data/lib/tasks/active_fedora_dev.rake +6 -5
- data/spec/config_helper.rb +14 -14
- data/spec/integration/associations_spec.rb +168 -455
- data/spec/integration/attributes_spec.rb +12 -11
- data/spec/integration/auditable_spec.rb +11 -11
- data/spec/integration/autosave_association_spec.rb +25 -0
- data/spec/integration/base_spec.rb +163 -163
- data/spec/integration/belongs_to_association_spec.rb +166 -0
- data/spec/integration/bug_spec.rb +7 -7
- data/spec/integration/collection_association_spec.rb +58 -0
- data/spec/integration/complex_rdf_datastream_spec.rb +88 -88
- data/spec/integration/datastream_collections_spec.rb +69 -69
- data/spec/integration/datastream_spec.rb +43 -43
- data/spec/integration/datastreams_spec.rb +63 -63
- data/spec/integration/delete_all_spec.rb +46 -39
- data/spec/integration/fedora_solr_sync_spec.rb +5 -5
- data/spec/integration/field_to_solr_name_spec.rb +34 -0
- data/spec/integration/full_featured_model_spec.rb +100 -101
- data/spec/integration/has_and_belongs_to_many_associations_spec.rb +341 -0
- data/spec/integration/has_many_associations_spec.rb +172 -24
- data/spec/integration/json_serialization_spec.rb +31 -0
- data/spec/integration/load_from_solr_spec.rb +48 -0
- data/spec/integration/model_spec.rb +35 -40
- data/spec/integration/nested_attribute_spec.rb +42 -43
- data/spec/integration/ntriples_datastream_spec.rb +131 -113
- data/spec/integration/om_datastream_spec.rb +67 -67
- data/spec/integration/persistence_spec.rb +7 -7
- data/spec/integration/rdf_nested_attributes_spec.rb +56 -56
- data/spec/integration/relation_delegation_spec.rb +26 -25
- data/spec/integration/relation_spec.rb +42 -0
- data/spec/integration/rels_ext_datastream_spec.rb +20 -20
- data/spec/integration/scoped_query_spec.rb +61 -51
- data/spec/integration/solr_instance_loader_spec.rb +5 -5
- data/spec/integration/solr_service_spec.rb +46 -46
- data/spec/samples/hydra-mods_article_datastream.rb +334 -334
- data/spec/samples/hydra-rights_metadata_datastream.rb +57 -57
- data/spec/samples/marpa-dc_datastream.rb +17 -17
- data/spec/samples/models/audio_record.rb +16 -16
- data/spec/samples/models/image.rb +2 -2
- data/spec/samples/models/mods_article.rb +5 -5
- data/spec/samples/models/oral_history.rb +18 -18
- data/spec/samples/models/seminar.rb +24 -24
- data/spec/samples/models/seminar_audio_file.rb +17 -17
- data/spec/samples/oral_history_sample_model.rb +21 -21
- data/spec/samples/special_thing.rb +14 -14
- data/spec/spec_helper.rb +11 -7
- data/spec/support/an_active_model.rb +2 -8
- data/spec/support/freeze_mocks.rb +12 -0
- data/spec/support/mock_fedora.rb +17 -16
- data/spec/unit/active_fedora_spec.rb +58 -60
- data/spec/unit/attributes_spec.rb +314 -0
- data/spec/unit/base_active_model_spec.rb +28 -27
- data/spec/unit/base_cma_spec.rb +5 -5
- data/spec/unit/base_datastream_management_spec.rb +27 -27
- data/spec/unit/base_extra_spec.rb +76 -48
- data/spec/unit/base_spec.rb +277 -348
- data/spec/unit/callback_spec.rb +18 -19
- data/spec/unit/code_configurator_spec.rb +17 -17
- data/spec/unit/config_spec.rb +8 -16
- data/spec/unit/content_model_spec.rb +79 -60
- data/spec/unit/datastream_collections_spec.rb +229 -229
- data/spec/unit/datastream_spec.rb +51 -63
- data/spec/unit/datastreams_spec.rb +87 -87
- data/spec/unit/file_configurator_spec.rb +217 -217
- data/spec/unit/has_and_belongs_to_many_collection_spec.rb +44 -25
- data/spec/unit/has_many_collection_spec.rb +26 -8
- data/spec/unit/inheritance_spec.rb +13 -12
- data/spec/unit/model_spec.rb +39 -45
- data/spec/unit/nom_datastream_spec.rb +15 -15
- data/spec/unit/ntriples_datastream_spec.rb +123 -118
- data/spec/unit/om_datastream_spec.rb +227 -233
- data/spec/unit/persistence_spec.rb +34 -15
- data/spec/unit/predicates_spec.rb +73 -73
- data/spec/unit/property_spec.rb +17 -9
- data/spec/unit/qualified_dublin_core_datastream_spec.rb +33 -33
- data/spec/unit/query_spec.rb +222 -198
- data/spec/unit/rdf_datastream_spec.rb +21 -28
- data/spec/unit/rdf_list_nested_attributes_spec.rb +34 -34
- data/spec/unit/rdf_list_spec.rb +65 -64
- data/spec/unit/rdf_node_spec.rb +7 -7
- data/spec/unit/rdf_xml_writer_spec.rb +10 -10
- data/spec/unit/rdfxml_rdf_datastream_spec.rb +27 -27
- data/spec/unit/relationship_graph_spec.rb +51 -51
- data/spec/unit/rels_ext_datastream_spec.rb +68 -74
- data/spec/unit/rspec_matchers/belong_to_associated_active_fedora_object_matcher_spec.rb +15 -15
- data/spec/unit/rspec_matchers/have_many_associated_active_fedora_objects_matcher_spec.rb +15 -15
- data/spec/unit/rspec_matchers/have_predicate_matcher_spec.rb +15 -15
- data/spec/unit/rspec_matchers/match_fedora_datastream_matcher_spec.rb +12 -12
- data/spec/unit/rubydora_connection_spec.rb +5 -5
- data/spec/unit/semantic_node_spec.rb +48 -107
- data/spec/unit/serializers_spec.rb +4 -4
- data/spec/unit/service_definitions_spec.rb +26 -26
- data/spec/unit/simple_datastream_spec.rb +17 -17
- data/spec/unit/solr_config_options_spec.rb +29 -28
- data/spec/unit/solr_digital_object_spec.rb +17 -25
- data/spec/unit/solr_service_spec.rb +95 -82
- data/spec/unit/unsaved_digital_object_spec.rb +24 -23
- data/spec/unit/validations_spec.rb +21 -21
- metadata +110 -159
- data/.rspec +0 -1
- data/.rubocop.yml +0 -1
- data/.rubocop_todo.yml +0 -938
- data/CONSOLE_GETTING_STARTED.textile +0 -1
- data/NOKOGIRI_DATASTREAMS.textile +0 -1
- data/README.textile +0 -116
- data/lib/active_fedora/associations/association_proxy.rb +0 -178
- data/lib/active_fedora/delegating.rb +0 -72
- data/lib/active_fedora/nokogiri_datastream.rb +0 -11
- data/spec/integration/delegating_spec.rb +0 -59
- data/spec/rails3_test_app/.gitignore +0 -4
- data/spec/rails3_test_app/.rspec +0 -1
- data/spec/rails3_test_app/Gemfile +0 -40
- data/spec/rails3_test_app/Rakefile +0 -7
- data/spec/rails3_test_app/app/controllers/application_controller.rb +0 -3
- data/spec/rails3_test_app/app/helpers/application_helper.rb +0 -2
- data/spec/rails3_test_app/app/views/layouts/application.html.erb +0 -14
- data/spec/rails3_test_app/config.ru +0 -4
- data/spec/rails3_test_app/config/application.rb +0 -42
- data/spec/rails3_test_app/config/boot.rb +0 -6
- data/spec/rails3_test_app/config/database.yml +0 -22
- data/spec/rails3_test_app/config/environment.rb +0 -5
- data/spec/rails3_test_app/config/environments/development.rb +0 -25
- data/spec/rails3_test_app/config/environments/production.rb +0 -49
- data/spec/rails3_test_app/config/environments/test.rb +0 -35
- data/spec/rails3_test_app/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/rails3_test_app/config/initializers/inflections.rb +0 -10
- data/spec/rails3_test_app/config/initializers/mime_types.rb +0 -5
- data/spec/rails3_test_app/config/initializers/secret_token.rb +0 -7
- data/spec/rails3_test_app/config/initializers/session_store.rb +0 -8
- data/spec/rails3_test_app/config/locales/en.yml +0 -5
- data/spec/rails3_test_app/config/routes.rb +0 -58
- data/spec/rails3_test_app/db/seeds.rb +0 -7
- data/spec/rails3_test_app/run_tests +0 -3
- data/spec/rails3_test_app/script/rails +0 -6
- data/spec/rails3_test_app/spec/spec_helper.rb +0 -27
- data/spec/rails3_test_app/spec/unit/rails_3_init.rb +0 -15
- data/spec/unit/association_proxy_spec.rb +0 -12
- data/spec/unit/base_delegate_spec.rb +0 -197
- data/spec/unit/base_delegate_to_spec.rb +0 -73
@@ -0,0 +1,19 @@
|
|
1
|
+
module ActiveFedora
|
2
|
+
module Calculations
|
3
|
+
|
4
|
+
# Get a count of the number of objects from solr
|
5
|
+
# Takes :conditions as an argument
|
6
|
+
def count(*args)
|
7
|
+
return apply_finder_options(args.first).count if args.any?
|
8
|
+
opts = {}
|
9
|
+
opts[:rows] = limit_value if limit_value
|
10
|
+
opts[:sort] = order_values if order_values
|
11
|
+
|
12
|
+
calculate :count, where_values, opts
|
13
|
+
end
|
14
|
+
|
15
|
+
def calculate(calculation, conditions, opts={})
|
16
|
+
SolrService.query(create_query(conditions), :raw=>true, :rows=>0)['response']['numFound']
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module ActiveFedora
|
2
|
+
module Delegation # :nodoc:
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
# This module creates compiled delegation methods dynamically at runtime, which makes
|
6
|
+
# subsequent calls to that method faster by avoiding method_missing. The delegations
|
7
|
+
# may vary depending on the klass of a relation, so we create a subclass of Relation
|
8
|
+
# for each different klass, and the delegations are compiled into that subclass only.
|
9
|
+
|
10
|
+
delegate :length, :collect, :map, :each, :all?, :include?, :to_ary, :to => :to_a
|
11
|
+
|
12
|
+
|
13
|
+
def method_missing(method, *args, &block)
|
14
|
+
if Array.method_defined?(method)
|
15
|
+
self.class.delegate method, :to => :to_a
|
16
|
+
to_a.send(method, *args, &block)
|
17
|
+
else
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,247 @@
|
|
1
|
+
module ActiveFedora
|
2
|
+
module FinderMethods
|
3
|
+
|
4
|
+
# Returns the first records that was found.
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# Person.where(name_t: 'Jones').first
|
8
|
+
# => #<Person @id="foo:123" @name='Jones' ... >
|
9
|
+
def first
|
10
|
+
if loaded?
|
11
|
+
@records.first
|
12
|
+
else
|
13
|
+
@first ||= limit(1).to_a[0]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the last record sorted by id. ID was chosen because this mimics
|
18
|
+
# how ActiveRecord would achieve the same behavior.
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
# Person.where(name_t: 'Jones').last
|
22
|
+
# => #<Person @id="foo:123" @name='Jones' ... >
|
23
|
+
def last
|
24
|
+
if loaded?
|
25
|
+
@records.last
|
26
|
+
else
|
27
|
+
@last ||= order('id desc').limit(1).to_a[0]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns an Array of objects of the Class that +find+ is being
|
32
|
+
# called on
|
33
|
+
#
|
34
|
+
# @param[String,Hash] args either a pid or a hash of conditions
|
35
|
+
# @option args [Integer] :rows when :all is passed, the maximum number of rows to load from solr
|
36
|
+
# @option args [Boolean] :cast when true, examine the model and cast it to the first known cModel
|
37
|
+
def find(*args)
|
38
|
+
return to_a.find { |*block_args| yield(*block_args) } if block_given?
|
39
|
+
options = args.extract_options!
|
40
|
+
options = options.dup
|
41
|
+
|
42
|
+
cast = if @klass == ActiveFedora::Base && !options.has_key?(:cast)
|
43
|
+
true
|
44
|
+
else
|
45
|
+
options.delete(:cast)
|
46
|
+
end
|
47
|
+
if options[:sort]
|
48
|
+
# Deprecate sort sometime?
|
49
|
+
sort = options.delete(:sort)
|
50
|
+
options[:order] ||= sort if sort.present?
|
51
|
+
end
|
52
|
+
|
53
|
+
if options.present?
|
54
|
+
options = args.first unless args.empty?
|
55
|
+
options = {conditions: options}
|
56
|
+
apply_finder_options(options)
|
57
|
+
else
|
58
|
+
raise ArgumentError, "#{self}.find() expects a pid. You provided `#{args.inspect}'" unless args.is_a? Array
|
59
|
+
find_with_ids(args, cast)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns true if the pid exists in the repository
|
64
|
+
# @param[String] pid
|
65
|
+
# @return[boolean]
|
66
|
+
def exists?(conditions)
|
67
|
+
conditions = conditions.id if Base === conditions
|
68
|
+
return false if !conditions
|
69
|
+
!!DigitalObject.find(self.klass, conditions)
|
70
|
+
rescue ActiveFedora::ObjectNotFoundError
|
71
|
+
false
|
72
|
+
end
|
73
|
+
|
74
|
+
# Returns a solr result matching the supplied conditions
|
75
|
+
# @param[Hash,String] conditions can either be specified as a string, or
|
76
|
+
# hash representing the query part of an solr statement. If a hash is
|
77
|
+
# provided, this method will generate conditions based simple equality
|
78
|
+
# combined using the boolean AND operator.
|
79
|
+
# @param[Hash] options
|
80
|
+
# @option opts [Array] :sort a list of fields to sort by
|
81
|
+
# @option opts [Array] :rows number of rows to return
|
82
|
+
def find_with_conditions(conditions, opts={})
|
83
|
+
#set default sort to created date ascending
|
84
|
+
unless opts.include?(:sort)
|
85
|
+
opts[:sort]=@klass.default_sort_params
|
86
|
+
end
|
87
|
+
SolrService.query(create_query(conditions), opts)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Yields the found ActiveFedora::Base object to the passed block
|
91
|
+
#
|
92
|
+
# @param [Hash] conditions the conditions for the solr search to match
|
93
|
+
# @param [Hash] opts
|
94
|
+
# @option opts [Boolean] :cast when true, examine the model and cast it to the first known cModel
|
95
|
+
def find_each( conditions={}, opts={})
|
96
|
+
cast = opts.delete(:cast)
|
97
|
+
find_in_batches(conditions, opts.merge({:fl=>SOLR_DOCUMENT_ID})) do |group|
|
98
|
+
group.each do |hit|
|
99
|
+
begin
|
100
|
+
yield(load_from_fedora(hit[SOLR_DOCUMENT_ID], cast))
|
101
|
+
rescue ActiveFedora::ObjectNotFoundError
|
102
|
+
logger.error "Although #{hit[SOLR_DOCUMENT_ID]} was found in Solr, it doesn't seem to exist in Fedora. The index is out of synch."
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Yields each batch of solr records that was found by the find +options+ as
|
109
|
+
# an array. The size of each batch is set by the <tt>:batch_size</tt>
|
110
|
+
# option; the default is 1000.
|
111
|
+
#
|
112
|
+
# Returns a solr result matching the supplied conditions
|
113
|
+
# @param[Hash] conditions solr conditions to match
|
114
|
+
# @param[Hash] options
|
115
|
+
# @option opts [Array] :sort a list of fields to sort by
|
116
|
+
# @option opts [Array] :rows number of rows to return
|
117
|
+
#
|
118
|
+
# @example
|
119
|
+
# Person.find_in_batches('age_t'=>'21', {:batch_size=>50}) do |group|
|
120
|
+
# group.each { |person| puts person['name_t'] }
|
121
|
+
# end
|
122
|
+
|
123
|
+
def find_in_batches conditions, opts={}
|
124
|
+
opts[:q] = create_query(conditions)
|
125
|
+
opts[:qt] = @klass.solr_query_handler
|
126
|
+
#set default sort to created date ascending
|
127
|
+
unless opts[:sort].present?
|
128
|
+
opts[:sort]= @klass.default_sort_params
|
129
|
+
end
|
130
|
+
|
131
|
+
batch_size = opts.delete(:batch_size) || 1000
|
132
|
+
|
133
|
+
counter = 0
|
134
|
+
begin
|
135
|
+
counter += 1
|
136
|
+
response = ActiveFedora::SolrService.instance.conn.paginate counter, batch_size, "select", :params => opts
|
137
|
+
docs = response["response"]["docs"]
|
138
|
+
yield docs
|
139
|
+
end while docs.has_next?
|
140
|
+
end
|
141
|
+
|
142
|
+
# Retrieve the Fedora object with the given pid, explore the returned object, determine its model
|
143
|
+
# using #{ActiveFedora::ContentModel.known_models_for} and cast to that class.
|
144
|
+
# Raises a ObjectNotFoundError if the object is not found.
|
145
|
+
# @param [String] pid of the object to load
|
146
|
+
# @param [Boolean] cast when true, cast the found object to the class of the first known model defined in it's RELS-EXT
|
147
|
+
#
|
148
|
+
# @example because the object hydra:dataset1 asserts it is a Dataset (hasModel info:fedora/afmodel:Dataset), return a Dataset object (not a Book).
|
149
|
+
# Book.find_one("hydra:dataset1")
|
150
|
+
def find_one(pid, cast=nil)
|
151
|
+
if where_values.empty?
|
152
|
+
load_from_fedora(pid, cast)
|
153
|
+
else
|
154
|
+
query = ActiveFedora::SolrService.construct_query_for_rel(where_values)
|
155
|
+
query += " AND _query_:\"{!raw f=id}#{pid}\""
|
156
|
+
to_enum(:find_each, query, {}).to_a.first
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
protected
|
161
|
+
|
162
|
+
def load_from_fedora(pid, cast)
|
163
|
+
cast = true if self == ActiveFedora::Base && cast.nil?
|
164
|
+
inner = DigitalObject.find(@klass, pid)
|
165
|
+
af_base = @klass.allocate.init_with(inner)
|
166
|
+
cast ? af_base.adapt_to_cmodel : af_base
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
def find_with_ids(ids, cast)
|
172
|
+
expects_array = ids.first.kind_of?(Array)
|
173
|
+
return ids.first if expects_array && ids.first.empty?
|
174
|
+
|
175
|
+
ids = ids.flatten.compact.uniq
|
176
|
+
|
177
|
+
case ids.size
|
178
|
+
when 0
|
179
|
+
raise ArgumentError, "Couldn't find #{@klass.name} without an ID"
|
180
|
+
when 1
|
181
|
+
result = find_one(ids.first, cast)
|
182
|
+
expects_array ? [ result ] : result
|
183
|
+
else
|
184
|
+
find_some(ids, cast)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def find_some(ids, cast)
|
189
|
+
ids.map{|id| find_one(id, cast)}
|
190
|
+
end
|
191
|
+
|
192
|
+
|
193
|
+
private
|
194
|
+
|
195
|
+
# Returns a solr query for the supplied conditions
|
196
|
+
# @param[Hash] conditions solr conditions to match
|
197
|
+
def create_query(conditions)
|
198
|
+
conditions.kind_of?(Hash) ? create_query_from_hash(conditions) : create_query_from_string(conditions)
|
199
|
+
end
|
200
|
+
|
201
|
+
def create_query_from_hash(conditions)
|
202
|
+
clauses = search_model_clause ? [search_model_clause] : []
|
203
|
+
conditions.each_pair do |key,value|
|
204
|
+
clauses << condition_to_clauses(key, value)
|
205
|
+
end
|
206
|
+
return "*:*" if clauses.empty?
|
207
|
+
clauses.compact.join(" AND ")
|
208
|
+
end
|
209
|
+
|
210
|
+
def condition_to_clauses(key, value)
|
211
|
+
unless value.nil?
|
212
|
+
# if the key is a property name, turn it into a solr field
|
213
|
+
if @klass.defined_attributes.key?(key)
|
214
|
+
# TODO Check to see if `key' is a possible solr field for this class, if it isn't try :searchable instead
|
215
|
+
key = ActiveFedora::SolrService.solr_name(key, :stored_searchable, type: :string)
|
216
|
+
end
|
217
|
+
|
218
|
+
if value.empty?
|
219
|
+
"-#{key}:['' TO *]"
|
220
|
+
elsif value.is_a? Array
|
221
|
+
value.map { |val| "#{key}:#{@klass.quote_for_solr(val)}" }
|
222
|
+
else
|
223
|
+
key = SOLR_DOCUMENT_ID if (key === :id || key === :pid)
|
224
|
+
escaped_value = @klass.quote_for_solr(value)
|
225
|
+
key.to_s.eql?(SOLR_DOCUMENT_ID) ? "#{key}:#{escaped_value}" : "#{key}:#{escaped_value}"
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def create_query_from_string(conditions)
|
231
|
+
model_clause = search_model_clause
|
232
|
+
if model_clause
|
233
|
+
conditions ? "#{model_clause} AND (#{conditions})" : model_clause
|
234
|
+
else
|
235
|
+
conditions
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
# Return the solr clause that queries for this type of class
|
240
|
+
def search_model_clause
|
241
|
+
unless @klass == ActiveFedora::Base
|
242
|
+
return ActiveFedora::SolrService.construct_query_for_rel(:has_model => @klass.to_class_uri)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
end
|
247
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module ActiveFedora
|
2
|
+
class Relation
|
3
|
+
class HashMerger # :nodoc:
|
4
|
+
end
|
5
|
+
|
6
|
+
class Merger # :nodoc:
|
7
|
+
attr_reader :relation, :values, :other
|
8
|
+
|
9
|
+
def initialize(relation, other)
|
10
|
+
@relation = relation
|
11
|
+
@values = other.values
|
12
|
+
@other = other
|
13
|
+
end
|
14
|
+
|
15
|
+
def merge
|
16
|
+
# TODO merge order
|
17
|
+
relation.where_values = relation.where_values.merge(other.where_values)
|
18
|
+
relation
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module ActiveFedora
|
2
|
+
module QueryMethods # :nodoc:
|
3
|
+
|
4
|
+
def extending_values
|
5
|
+
@values[:extending] || []
|
6
|
+
end
|
7
|
+
|
8
|
+
def extending_values=(values)
|
9
|
+
raise ImmutableRelation if @loaded
|
10
|
+
@values[:extending] = values
|
11
|
+
end
|
12
|
+
|
13
|
+
def where_values
|
14
|
+
@values[:where] ||= {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def where_values=(values)
|
18
|
+
raise ImmutableRelation if @loaded
|
19
|
+
@values[:where] = values
|
20
|
+
end
|
21
|
+
|
22
|
+
def order_values
|
23
|
+
@values[:order] || []
|
24
|
+
end
|
25
|
+
|
26
|
+
def order_values=(values)
|
27
|
+
raise ImmutableRelation if @loaded
|
28
|
+
@values[:order] = values
|
29
|
+
end
|
30
|
+
|
31
|
+
def limit_value
|
32
|
+
@values[:limit]
|
33
|
+
end
|
34
|
+
|
35
|
+
def limit_value=(value)
|
36
|
+
raise ImmutableRelation if @loaded
|
37
|
+
@values[:limit] = value
|
38
|
+
end
|
39
|
+
|
40
|
+
def none! # :nodoc:
|
41
|
+
extending!(NullRelation)
|
42
|
+
end
|
43
|
+
|
44
|
+
def extending!(*modules, &block) # :nodoc:
|
45
|
+
modules << Module.new(&block) if block
|
46
|
+
modules.flatten!
|
47
|
+
|
48
|
+
self.extending_values += modules
|
49
|
+
extend(*extending_values) if extending_values.any?
|
50
|
+
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
54
|
+
def select
|
55
|
+
to_a.select { |*block_args| yield(*block_args) }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'active_fedora/relation/merger'
|
2
|
+
|
3
|
+
module ActiveFedora
|
4
|
+
module SpawnMethods
|
5
|
+
|
6
|
+
# This is overridden by Associations::CollectionProxy
|
7
|
+
def spawn #:nodoc:
|
8
|
+
clone
|
9
|
+
end
|
10
|
+
|
11
|
+
# Merges in the conditions from <tt>other</tt>, if <tt>other</tt> is an <tt>ActiveRecord::Relation</tt>.
|
12
|
+
# Returns an array representing the intersection of the resulting records with <tt>other</tt>, if <tt>other</tt> is an array.
|
13
|
+
# Post.where(published: true).joins(:comments).merge( Comment.where(spam: false) )
|
14
|
+
# # Performs a single join query with both where conditions.
|
15
|
+
#
|
16
|
+
# recent_posts = Post.order('created_at DESC').first(5)
|
17
|
+
# Post.where(published: true).merge(recent_posts)
|
18
|
+
# # Returns the intersection of all published posts with the 5 most recently created posts.
|
19
|
+
# # (This is just an example. You'd probably want to do this with a single query!)
|
20
|
+
#
|
21
|
+
# Procs will be evaluated by merge:
|
22
|
+
#
|
23
|
+
# Post.where(published: true).merge(-> { joins(:comments) })
|
24
|
+
# # => Post.where(published: true).joins(:comments)
|
25
|
+
#
|
26
|
+
# This is mainly intended for sharing common conditions between multiple associations.
|
27
|
+
def merge(other)
|
28
|
+
if other.is_a?(Array)
|
29
|
+
to_a & other
|
30
|
+
elsif other
|
31
|
+
spawn.merge!(other)
|
32
|
+
else
|
33
|
+
self
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def merge!(other) # :nodoc:
|
38
|
+
if !other.is_a?(Relation) && other.respond_to?(:to_proc)
|
39
|
+
instance_exec(&other)
|
40
|
+
else
|
41
|
+
klass = other.is_a?(Hash) ? Relation::HashMerger : Relation::Merger
|
42
|
+
klass.new(self, other).merge
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -3,7 +3,6 @@ module ActiveFedora
|
|
3
3
|
|
4
4
|
attr_accessor :relationships, :dirty
|
5
5
|
|
6
|
-
|
7
6
|
def initialize
|
8
7
|
self.dirty = false
|
9
8
|
self.relationships = Hash.new { |h, k| h[k] = [] }
|
@@ -98,6 +97,5 @@ module ActiveFedora
|
|
98
97
|
return predicate if predicate.kind_of? RDF::URI
|
99
98
|
ActiveFedora::Predicates.find_graph_predicate(predicate)
|
100
99
|
end
|
101
|
-
|
102
100
|
end
|
103
101
|
end
|
@@ -6,6 +6,7 @@ module ActiveFedora
|
|
6
6
|
class RelsExtDatastream < Datastream
|
7
7
|
|
8
8
|
attr_accessor :model
|
9
|
+
delegate :relationships, to: :model
|
9
10
|
|
10
11
|
def self.default_attributes
|
11
12
|
super.merge(:controlGroup => 'X', :mimeType => 'application/rdf+xml')
|
@@ -36,10 +37,6 @@ module ActiveFedora
|
|
36
37
|
model.relationships_are_dirty = false
|
37
38
|
end
|
38
39
|
|
39
|
-
def relationships
|
40
|
-
model.relationships
|
41
|
-
end
|
42
|
-
|
43
40
|
# Populate a RelsExtDatastream object based on the "datastream" content
|
44
41
|
# Assumes that the datastream contains RDF XML from a Fedora RELS-EXT datastream
|
45
42
|
# @param [String] xml the "rdf" node
|