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.
Files changed (215) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +15 -5
  4. data/CONTRIBUTING.md +2 -0
  5. data/Gemfile +0 -2
  6. data/History.txt +2 -32
  7. data/README.md +143 -0
  8. data/Rakefile +5 -7
  9. data/active-fedora.gemspec +9 -9
  10. data/gemfiles/rails3.gemfile +11 -0
  11. data/gemfiles/rails4.gemfile +10 -0
  12. data/lib/active_fedora.rb +31 -4
  13. data/lib/active_fedora/association_relation.rb +18 -0
  14. data/lib/active_fedora/associations.rb +38 -171
  15. data/lib/active_fedora/associations/association.rb +163 -0
  16. data/lib/active_fedora/associations/association_scope.rb +39 -0
  17. data/lib/active_fedora/associations/belongs_to_association.rb +47 -25
  18. data/lib/active_fedora/associations/builder/association.rb +55 -0
  19. data/lib/active_fedora/associations/builder/belongs_to.rb +100 -0
  20. data/lib/active_fedora/associations/builder/collection_association.rb +56 -0
  21. data/lib/active_fedora/associations/builder/has_and_belongs_to_many.rb +30 -0
  22. data/lib/active_fedora/associations/builder/has_many.rb +63 -0
  23. data/lib/active_fedora/associations/builder/singular_association.rb +32 -0
  24. data/lib/active_fedora/associations/{association_collection.rb → collection_association.rb} +203 -53
  25. data/lib/active_fedora/associations/collection_proxy.rb +862 -0
  26. data/lib/active_fedora/associations/has_and_belongs_to_many_association.rb +35 -25
  27. data/lib/active_fedora/associations/has_many_association.rb +36 -11
  28. data/lib/active_fedora/associations/singular_association.rb +62 -0
  29. data/lib/active_fedora/attributes.rb +43 -139
  30. data/lib/active_fedora/autosave_association.rb +317 -0
  31. data/lib/active_fedora/base.rb +10 -327
  32. data/lib/active_fedora/callbacks.rb +1 -3
  33. data/lib/active_fedora/content_model.rb +16 -0
  34. data/lib/active_fedora/core.rb +151 -0
  35. data/lib/active_fedora/datastream_attribute.rb +76 -0
  36. data/lib/active_fedora/datastream_hash.rb +8 -13
  37. data/lib/active_fedora/datastreams.rb +39 -26
  38. data/lib/active_fedora/digital_object.rb +2 -2
  39. data/lib/active_fedora/fedora_attributes.rb +45 -0
  40. data/lib/active_fedora/fixture_loader.rb +1 -1
  41. data/lib/active_fedora/indexing.rb +6 -1
  42. data/lib/active_fedora/model.rb +0 -17
  43. data/lib/active_fedora/nested_attributes.rb +2 -2
  44. data/lib/active_fedora/null_relation.rb +7 -0
  45. data/lib/active_fedora/om_datastream.rb +3 -4
  46. data/lib/active_fedora/persistence.rb +41 -29
  47. data/lib/active_fedora/querying.rb +2 -163
  48. data/lib/active_fedora/rdf.rb +1 -0
  49. data/lib/active_fedora/rdf/indexing.rb +67 -0
  50. data/lib/active_fedora/rdf_datastream.rb +2 -50
  51. data/lib/active_fedora/rdf_node.rb +12 -7
  52. data/lib/active_fedora/rdf_node/term_proxy.rb +30 -21
  53. data/lib/active_fedora/rdfxml_rdf_datastream.rb +1 -1
  54. data/lib/active_fedora/reflection.rb +163 -20
  55. data/lib/active_fedora/relation.rb +33 -130
  56. data/lib/active_fedora/relation/calculations.rb +19 -0
  57. data/lib/active_fedora/relation/delegation.rb +22 -0
  58. data/lib/active_fedora/relation/finder_methods.rb +247 -0
  59. data/lib/active_fedora/relation/merger.rb +22 -0
  60. data/lib/active_fedora/relation/query_methods.rb +58 -0
  61. data/lib/active_fedora/relation/spawn_methods.rb +46 -0
  62. data/lib/active_fedora/relationship_graph.rb +0 -2
  63. data/lib/active_fedora/rels_ext_datastream.rb +1 -4
  64. data/lib/active_fedora/rubydora_connection.rb +1 -1
  65. data/lib/active_fedora/scoping.rb +20 -0
  66. data/lib/active_fedora/scoping/default.rb +38 -0
  67. data/lib/active_fedora/scoping/named.rb +32 -0
  68. data/lib/active_fedora/semantic_node.rb +54 -106
  69. data/lib/active_fedora/serialization.rb +19 -0
  70. data/lib/active_fedora/sharding.rb +58 -0
  71. data/lib/active_fedora/solr_digital_object.rb +15 -5
  72. data/lib/active_fedora/solr_instance_loader.rb +1 -1
  73. data/lib/active_fedora/solr_service.rb +1 -1
  74. data/lib/active_fedora/unsaved_digital_object.rb +6 -4
  75. data/lib/active_fedora/version.rb +1 -1
  76. data/lib/tasks/active_fedora.rake +3 -0
  77. data/lib/tasks/active_fedora_dev.rake +6 -5
  78. data/spec/config_helper.rb +14 -14
  79. data/spec/integration/associations_spec.rb +168 -455
  80. data/spec/integration/attributes_spec.rb +12 -11
  81. data/spec/integration/auditable_spec.rb +11 -11
  82. data/spec/integration/autosave_association_spec.rb +25 -0
  83. data/spec/integration/base_spec.rb +163 -163
  84. data/spec/integration/belongs_to_association_spec.rb +166 -0
  85. data/spec/integration/bug_spec.rb +7 -7
  86. data/spec/integration/collection_association_spec.rb +58 -0
  87. data/spec/integration/complex_rdf_datastream_spec.rb +88 -88
  88. data/spec/integration/datastream_collections_spec.rb +69 -69
  89. data/spec/integration/datastream_spec.rb +43 -43
  90. data/spec/integration/datastreams_spec.rb +63 -63
  91. data/spec/integration/delete_all_spec.rb +46 -39
  92. data/spec/integration/fedora_solr_sync_spec.rb +5 -5
  93. data/spec/integration/field_to_solr_name_spec.rb +34 -0
  94. data/spec/integration/full_featured_model_spec.rb +100 -101
  95. data/spec/integration/has_and_belongs_to_many_associations_spec.rb +341 -0
  96. data/spec/integration/has_many_associations_spec.rb +172 -24
  97. data/spec/integration/json_serialization_spec.rb +31 -0
  98. data/spec/integration/load_from_solr_spec.rb +48 -0
  99. data/spec/integration/model_spec.rb +35 -40
  100. data/spec/integration/nested_attribute_spec.rb +42 -43
  101. data/spec/integration/ntriples_datastream_spec.rb +131 -113
  102. data/spec/integration/om_datastream_spec.rb +67 -67
  103. data/spec/integration/persistence_spec.rb +7 -7
  104. data/spec/integration/rdf_nested_attributes_spec.rb +56 -56
  105. data/spec/integration/relation_delegation_spec.rb +26 -25
  106. data/spec/integration/relation_spec.rb +42 -0
  107. data/spec/integration/rels_ext_datastream_spec.rb +20 -20
  108. data/spec/integration/scoped_query_spec.rb +61 -51
  109. data/spec/integration/solr_instance_loader_spec.rb +5 -5
  110. data/spec/integration/solr_service_spec.rb +46 -46
  111. data/spec/samples/hydra-mods_article_datastream.rb +334 -334
  112. data/spec/samples/hydra-rights_metadata_datastream.rb +57 -57
  113. data/spec/samples/marpa-dc_datastream.rb +17 -17
  114. data/spec/samples/models/audio_record.rb +16 -16
  115. data/spec/samples/models/image.rb +2 -2
  116. data/spec/samples/models/mods_article.rb +5 -5
  117. data/spec/samples/models/oral_history.rb +18 -18
  118. data/spec/samples/models/seminar.rb +24 -24
  119. data/spec/samples/models/seminar_audio_file.rb +17 -17
  120. data/spec/samples/oral_history_sample_model.rb +21 -21
  121. data/spec/samples/special_thing.rb +14 -14
  122. data/spec/spec_helper.rb +11 -7
  123. data/spec/support/an_active_model.rb +2 -8
  124. data/spec/support/freeze_mocks.rb +12 -0
  125. data/spec/support/mock_fedora.rb +17 -16
  126. data/spec/unit/active_fedora_spec.rb +58 -60
  127. data/spec/unit/attributes_spec.rb +314 -0
  128. data/spec/unit/base_active_model_spec.rb +28 -27
  129. data/spec/unit/base_cma_spec.rb +5 -5
  130. data/spec/unit/base_datastream_management_spec.rb +27 -27
  131. data/spec/unit/base_extra_spec.rb +76 -48
  132. data/spec/unit/base_spec.rb +277 -348
  133. data/spec/unit/callback_spec.rb +18 -19
  134. data/spec/unit/code_configurator_spec.rb +17 -17
  135. data/spec/unit/config_spec.rb +8 -16
  136. data/spec/unit/content_model_spec.rb +79 -60
  137. data/spec/unit/datastream_collections_spec.rb +229 -229
  138. data/spec/unit/datastream_spec.rb +51 -63
  139. data/spec/unit/datastreams_spec.rb +87 -87
  140. data/spec/unit/file_configurator_spec.rb +217 -217
  141. data/spec/unit/has_and_belongs_to_many_collection_spec.rb +44 -25
  142. data/spec/unit/has_many_collection_spec.rb +26 -8
  143. data/spec/unit/inheritance_spec.rb +13 -12
  144. data/spec/unit/model_spec.rb +39 -45
  145. data/spec/unit/nom_datastream_spec.rb +15 -15
  146. data/spec/unit/ntriples_datastream_spec.rb +123 -118
  147. data/spec/unit/om_datastream_spec.rb +227 -233
  148. data/spec/unit/persistence_spec.rb +34 -15
  149. data/spec/unit/predicates_spec.rb +73 -73
  150. data/spec/unit/property_spec.rb +17 -9
  151. data/spec/unit/qualified_dublin_core_datastream_spec.rb +33 -33
  152. data/spec/unit/query_spec.rb +222 -198
  153. data/spec/unit/rdf_datastream_spec.rb +21 -28
  154. data/spec/unit/rdf_list_nested_attributes_spec.rb +34 -34
  155. data/spec/unit/rdf_list_spec.rb +65 -64
  156. data/spec/unit/rdf_node_spec.rb +7 -7
  157. data/spec/unit/rdf_xml_writer_spec.rb +10 -10
  158. data/spec/unit/rdfxml_rdf_datastream_spec.rb +27 -27
  159. data/spec/unit/relationship_graph_spec.rb +51 -51
  160. data/spec/unit/rels_ext_datastream_spec.rb +68 -74
  161. data/spec/unit/rspec_matchers/belong_to_associated_active_fedora_object_matcher_spec.rb +15 -15
  162. data/spec/unit/rspec_matchers/have_many_associated_active_fedora_objects_matcher_spec.rb +15 -15
  163. data/spec/unit/rspec_matchers/have_predicate_matcher_spec.rb +15 -15
  164. data/spec/unit/rspec_matchers/match_fedora_datastream_matcher_spec.rb +12 -12
  165. data/spec/unit/rubydora_connection_spec.rb +5 -5
  166. data/spec/unit/semantic_node_spec.rb +48 -107
  167. data/spec/unit/serializers_spec.rb +4 -4
  168. data/spec/unit/service_definitions_spec.rb +26 -26
  169. data/spec/unit/simple_datastream_spec.rb +17 -17
  170. data/spec/unit/solr_config_options_spec.rb +29 -28
  171. data/spec/unit/solr_digital_object_spec.rb +17 -25
  172. data/spec/unit/solr_service_spec.rb +95 -82
  173. data/spec/unit/unsaved_digital_object_spec.rb +24 -23
  174. data/spec/unit/validations_spec.rb +21 -21
  175. metadata +110 -159
  176. data/.rspec +0 -1
  177. data/.rubocop.yml +0 -1
  178. data/.rubocop_todo.yml +0 -938
  179. data/CONSOLE_GETTING_STARTED.textile +0 -1
  180. data/NOKOGIRI_DATASTREAMS.textile +0 -1
  181. data/README.textile +0 -116
  182. data/lib/active_fedora/associations/association_proxy.rb +0 -178
  183. data/lib/active_fedora/delegating.rb +0 -72
  184. data/lib/active_fedora/nokogiri_datastream.rb +0 -11
  185. data/spec/integration/delegating_spec.rb +0 -59
  186. data/spec/rails3_test_app/.gitignore +0 -4
  187. data/spec/rails3_test_app/.rspec +0 -1
  188. data/spec/rails3_test_app/Gemfile +0 -40
  189. data/spec/rails3_test_app/Rakefile +0 -7
  190. data/spec/rails3_test_app/app/controllers/application_controller.rb +0 -3
  191. data/spec/rails3_test_app/app/helpers/application_helper.rb +0 -2
  192. data/spec/rails3_test_app/app/views/layouts/application.html.erb +0 -14
  193. data/spec/rails3_test_app/config.ru +0 -4
  194. data/spec/rails3_test_app/config/application.rb +0 -42
  195. data/spec/rails3_test_app/config/boot.rb +0 -6
  196. data/spec/rails3_test_app/config/database.yml +0 -22
  197. data/spec/rails3_test_app/config/environment.rb +0 -5
  198. data/spec/rails3_test_app/config/environments/development.rb +0 -25
  199. data/spec/rails3_test_app/config/environments/production.rb +0 -49
  200. data/spec/rails3_test_app/config/environments/test.rb +0 -35
  201. data/spec/rails3_test_app/config/initializers/backtrace_silencers.rb +0 -7
  202. data/spec/rails3_test_app/config/initializers/inflections.rb +0 -10
  203. data/spec/rails3_test_app/config/initializers/mime_types.rb +0 -5
  204. data/spec/rails3_test_app/config/initializers/secret_token.rb +0 -7
  205. data/spec/rails3_test_app/config/initializers/session_store.rb +0 -8
  206. data/spec/rails3_test_app/config/locales/en.yml +0 -5
  207. data/spec/rails3_test_app/config/routes.rb +0 -58
  208. data/spec/rails3_test_app/db/seeds.rb +0 -7
  209. data/spec/rails3_test_app/run_tests +0 -3
  210. data/spec/rails3_test_app/script/rails +0 -6
  211. data/spec/rails3_test_app/spec/spec_helper.rb +0 -27
  212. data/spec/rails3_test_app/spec/unit/rails_3_init.rb +0 -15
  213. data/spec/unit/association_proxy_spec.rb +0 -12
  214. data/spec/unit/base_delegate_spec.rb +0 -197
  215. 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