thinking-sphinx 3.1.2 → 3.1.3

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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -0
  3. data/Appraisals +7 -3
  4. data/HISTORY +12 -0
  5. data/README.textile +5 -3
  6. data/gemfiles/rails_3_2.gemfile +1 -1
  7. data/gemfiles/rails_4_0.gemfile +1 -1
  8. data/gemfiles/rails_4_1.gemfile +1 -1
  9. data/gemfiles/rails_4_2.gemfile +11 -0
  10. data/lib/thinking_sphinx.rb +1 -1
  11. data/lib/thinking_sphinx/active_record.rb +1 -1
  12. data/lib/thinking_sphinx/active_record/callbacks/delete_callbacks.rb +3 -1
  13. data/lib/thinking_sphinx/active_record/callbacks/delta_callbacks.rb +1 -1
  14. data/lib/thinking_sphinx/active_record/filter_reflection.rb +75 -0
  15. data/lib/thinking_sphinx/active_record/polymorpher.rb +4 -4
  16. data/lib/thinking_sphinx/active_record/property_query.rb +1 -1
  17. data/lib/thinking_sphinx/active_record/simple_many_query.rb +1 -1
  18. data/lib/thinking_sphinx/active_record/sql_builder.rb +0 -4
  19. data/lib/thinking_sphinx/active_record/sql_builder/statement.rb +0 -1
  20. data/lib/thinking_sphinx/configuration.rb +6 -3
  21. data/lib/thinking_sphinx/core/index.rb +1 -1
  22. data/lib/thinking_sphinx/excerpter.rb +4 -1
  23. data/lib/thinking_sphinx/facet_search.rb +8 -2
  24. data/lib/thinking_sphinx/index_set.rb +33 -11
  25. data/lib/thinking_sphinx/middlewares/inquirer.rb +1 -1
  26. data/lib/thinking_sphinx/middlewares/sphinxql.rb +3 -1
  27. data/lib/thinking_sphinx/railtie.rb +4 -2
  28. data/lib/thinking_sphinx/real_time/callbacks/real_time_callbacks.rb +2 -4
  29. data/lib/thinking_sphinx/real_time/index.rb +2 -0
  30. data/lib/thinking_sphinx/real_time/index/template.rb +1 -1
  31. data/spec/acceptance/big_integers_spec.rb +27 -6
  32. data/spec/acceptance/facets_spec.rb +1 -2
  33. data/spec/acceptance/real_time_updates_spec.rb +8 -0
  34. data/spec/acceptance/remove_deleted_records_spec.rb +4 -2
  35. data/spec/acceptance/searching_across_schemas_spec.rb +38 -0
  36. data/spec/acceptance/searching_with_sti_spec.rb +19 -7
  37. data/spec/internal/app/indices/bird_index.rb +4 -0
  38. data/spec/internal/app/indices/product_index.rb +21 -0
  39. data/spec/internal/db/schema.rb +9 -9
  40. data/spec/spec_helper.rb +2 -1
  41. data/spec/support/multi_schema.rb +46 -0
  42. data/spec/thinking_sphinx/active_record/callbacks/delta_callbacks_spec.rb +5 -3
  43. data/spec/thinking_sphinx/active_record/filter_reflection_spec.rb +172 -0
  44. data/spec/thinking_sphinx/active_record/polymorpher_spec.rb +18 -11
  45. data/spec/thinking_sphinx/active_record/sql_builder_spec.rb +0 -105
  46. data/spec/thinking_sphinx/configuration_spec.rb +0 -13
  47. data/spec/thinking_sphinx/facet_search_spec.rb +1 -2
  48. data/spec/thinking_sphinx/index_set_spec.rb +31 -13
  49. data/spec/thinking_sphinx/middlewares/inquirer_spec.rb +19 -0
  50. data/spec/thinking_sphinx/middlewares/sphinxql_spec.rb +6 -4
  51. data/thinking-sphinx.gemspec +1 -1
  52. metadata +13 -6
  53. data/lib/thinking_sphinx/active_record/filtered_reflection.rb +0 -75
  54. data/spec/thinking_sphinx/active_record/filtered_reflection_spec.rb +0 -141
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 629217e38872edc12e92be134409a509b84f1304
4
- data.tar.gz: 4b19eec90cfe3b560b1fcdd56a7018f07704ec94
3
+ metadata.gz: c17f93cf2e09238f8df63a50264d09abe50051ba
4
+ data.tar.gz: 90d74a5a5d8f5b7edc71826ec67adeb9ae4550b3
5
5
  SHA512:
6
- metadata.gz: 5116aad817ad119c97f05ec5bcdf330ca89ecae39ecac5695c4b9573ba062a88e25b6c8db22c596a32ec57ca8c044b2805360696b4b6342196d19b775886e340
7
- data.tar.gz: 6923c30ad7163f0ec5c286b5cf98403c27618dc57191bff659808000f9f51bcf2e1ef0eec22fbf6ecc54752a9e1e6474d6e62a65b65db6cc462d8657beae183e
6
+ metadata.gz: c861cf2251899f29b7f82d7c471918f9147042792f5856e5205f4dc431dfac38e1e41204e74415710848ce8d1ce72333c296cf695250930d3070aa55f629ff48
7
+ data.tar.gz: af1e25122e4710693c232f98e1ffd9a03092222417a2b5f20a274dcabc30785047f05bade7212689de939ee2724ce47161a665b14b6b14731ef8220d76bf75c1
data/.travis.yml CHANGED
@@ -19,3 +19,5 @@ env:
19
19
  gemfile:
20
20
  - gemfiles/rails_3_2.gemfile
21
21
  - gemfiles/rails_4_0.gemfile
22
+ - gemfiles/rails_4_1.gemfile
23
+ - gemfiles/rails_4_2.gemfile
data/Appraisals CHANGED
@@ -1,11 +1,15 @@
1
1
  appraise 'rails_3_2' do
2
- gem 'rails', '~> 3.2.0'
2
+ gem 'rails', '~> 3.2.21'
3
3
  end
4
4
 
5
5
  appraise 'rails_4_0' do
6
- gem 'rails', '~> 4.0.2'
6
+ gem 'rails', '~> 4.0.12'
7
7
  end
8
8
 
9
9
  appraise 'rails_4_1' do
10
- gem 'rails', '~> 4.1.0.beta1'
10
+ gem 'rails', '~> 4.1.8'
11
+ end
12
+
13
+ appraise 'rails_4_2' do
14
+ gem 'rails', '~> 4.2.0'
11
15
  end
data/HISTORY CHANGED
@@ -1,3 +1,15 @@
1
+ 2015-01-21: 3.1.3
2
+ * [CHANGE] Log excerpt SphinxQL queries just like the search queries.
3
+ * [CHANGE] Load Railtie if Rails::Railtie is defined, instead of just Rails (Andrew Cone).
4
+ * [CHANGE] Convert raw Sphinx results to an array when querying (Bryan Ricker).
5
+ * [FIX] Generate de-polymorphised associations properly for Rails 4.2
6
+ * [FIX] Use reflect_on_association instead of reflections, to stick to the public ActiveRecord::Base API.
7
+ * [FIX] Don't load ActiveRecord early - fixes a warning in Rails 4.2.
8
+ * [FEATURE] Allow for custom offset references with the :offset_as option - thus one model across many schemas with Apartment can be treated differently.
9
+ * [FEATURE] Allow for custom IndexSet classes.
10
+ * [FIX] Don't double-up on STI filtering, already handled by Rails.
11
+ * [CHANGE] Add bigint support for real-time indices, and use bigints for the sphinx_internal_id attribute (mapped to model primary keys) (Chance Downs).
12
+
1
13
  2014-11-04: 3.1.2
2
14
  * [CHANGE] regenerate task now only deletes index files for real-time indices.
3
15
  * [CHANGE] Raise an exception when a populated search query is modified (as it can't be requeried).
data/README.textile CHANGED
@@ -1,11 +1,13 @@
1
1
  h1. Thinking Sphinx
2
2
 
3
- Thinking Sphinx is a library for connecting ActiveRecord to the Sphinx full-text search tool, and integrates closely with Rails (but also works with other Ruby web frameworks). The current release is v3.1.1.
3
+ Thinking Sphinx is a library for connecting ActiveRecord to the Sphinx full-text search tool, and integrates closely with Rails (but also works with other Ruby web frameworks). The current release is v3.1.3.
4
4
 
5
5
  h2. Upgrading
6
6
 
7
7
  Please refer to the release notes for any changes you need to make when upgrading:
8
8
 
9
+ * "v3.1.3":https://github.com/pat/thinking-sphinx/releases/tag/v3.1.3
10
+ * "v3.1.2":https://github.com/pat/thinking-sphinx/releases/tag/v3.1.2
9
11
  * "v3.1.1":https://github.com/pat/thinking-sphinx/releases/tag/v3.1.1
10
12
  * "v3.1.0":https://github.com/pat/thinking-sphinx/releases/tag/v3.1.0
11
13
  * "v3.0.6":https://github.com/pat/thinking-sphinx/releases/tag/v3.0.6
@@ -18,7 +20,7 @@ It's a gem, so install it like you would any other gem. You will also need to sp
18
20
 
19
21
  <pre><code>gem 'mysql2', '~> 0.3.13', :platform => :ruby
20
22
  gem 'jdbc-mysql', '~> 5.1.28', :platform => :jruby
21
- gem 'thinking-sphinx', '~> 3.1.1'</code></pre>
23
+ gem 'thinking-sphinx', '~> 3.1.3'</code></pre>
22
24
 
23
25
  The MySQL gems mentioned are required for connecting to Sphinx, so please include it even when you're using PostgreSQL for your database.
24
26
 
@@ -75,4 +77,4 @@ You can then run the unit tests with @rake spec:unit@, the acceptance tests with
75
77
 
76
78
  h2. Licence
77
79
 
78
- Copyright (c) 2007-2014, Thinking Sphinx is developed and maintained by Pat Allan, and is released under the open MIT Licence. Many thanks to "all who have contributed patches":https://github.com/pat/thinking-sphinx/contributors.
80
+ Copyright (c) 2007-2015, Thinking Sphinx is developed and maintained by Pat Allan, and is released under the open MIT Licence. Many thanks to "all who have contributed patches":https://github.com/pat/thinking-sphinx/contributors.
@@ -6,6 +6,6 @@ gem "mysql2", "~> 0.3.12b4", :platform=>:ruby
6
6
  gem "pg", "~> 0.16.0", :platform=>:ruby
7
7
  gem "activerecord-jdbcmysql-adapter", "~> 1.3.4", :platform=>:jruby
8
8
  gem "activerecord-jdbcpostgresql-adapter", "~> 1.3.4", :platform=>:jruby
9
- gem "rails", "~> 3.2.0"
9
+ gem "rails", "~> 3.2.21"
10
10
 
11
11
  gemspec :path=>"../"
@@ -6,6 +6,6 @@ gem "mysql2", "~> 0.3.12b4", :platform=>:ruby
6
6
  gem "pg", "~> 0.16.0", :platform=>:ruby
7
7
  gem "activerecord-jdbcmysql-adapter", "~> 1.3.4", :platform=>:jruby
8
8
  gem "activerecord-jdbcpostgresql-adapter", "~> 1.3.4", :platform=>:jruby
9
- gem "rails", "~> 4.0.2"
9
+ gem "rails", "~> 4.0.12"
10
10
 
11
11
  gemspec :path=>"../"
@@ -6,6 +6,6 @@ gem "mysql2", "~> 0.3.12b4", :platform=>:ruby
6
6
  gem "pg", "~> 0.16.0", :platform=>:ruby
7
7
  gem "activerecord-jdbcmysql-adapter", "~> 1.3.4", :platform=>:jruby
8
8
  gem "activerecord-jdbcpostgresql-adapter", "~> 1.3.4", :platform=>:jruby
9
- gem "rails", "~> 4.1.0.beta1"
9
+ gem "rails", "~> 4.1.8"
10
10
 
11
11
  gemspec :path=>"../"
@@ -0,0 +1,11 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "mysql2", "~> 0.3.12b4", :platform=>:ruby
6
+ gem "pg", "~> 0.16.0", :platform=>:ruby
7
+ gem "activerecord-jdbcmysql-adapter", "~> 1.3.4", :platform=>:jruby
8
+ gem "activerecord-jdbcpostgresql-adapter", "~> 1.3.4", :platform=>:jruby
9
+ gem "rails", "~> 4.2.0"
10
+
11
+ gemspec :path=>"../"
@@ -77,4 +77,4 @@ require 'thinking_sphinx/distributed'
77
77
  require 'thinking_sphinx/logger'
78
78
  require 'thinking_sphinx/real_time'
79
79
 
80
- require 'thinking_sphinx/railtie' if defined?(Rails)
80
+ require 'thinking_sphinx/railtie' if defined?(Rails::Railtie)
@@ -14,7 +14,7 @@ require 'thinking_sphinx/active_record/column'
14
14
  require 'thinking_sphinx/active_record/column_sql_presenter'
15
15
  require 'thinking_sphinx/active_record/database_adapters'
16
16
  require 'thinking_sphinx/active_record/field'
17
- require 'thinking_sphinx/active_record/filtered_reflection'
17
+ require 'thinking_sphinx/active_record/filter_reflection'
18
18
  require 'thinking_sphinx/active_record/index'
19
19
  require 'thinking_sphinx/active_record/interpreter'
20
20
  require 'thinking_sphinx/active_record/join_association'
@@ -14,6 +14,8 @@ class ThinkingSphinx::ActiveRecord::Callbacks::DeleteCallbacks <
14
14
  private
15
15
 
16
16
  def indices
17
- ThinkingSphinx::IndexSet.new([instance.class], []).to_a
17
+ ThinkingSphinx::Configuration.instance.index_set_class.new(
18
+ :classes => [instance.class]
19
+ ).to_a
18
20
  end
19
21
  end
@@ -42,7 +42,7 @@ class ThinkingSphinx::ActiveRecord::Callbacks::DeltaCallbacks <
42
42
  end
43
43
 
44
44
  def indices
45
- @indices ||= ThinkingSphinx::IndexSet.new [instance.class], []
45
+ @indices ||= config.index_set_class.new :classes => [instance.class]
46
46
  end
47
47
 
48
48
  def processors
@@ -0,0 +1,75 @@
1
+ class ThinkingSphinx::ActiveRecord::FilterReflection
2
+ attr_reader :reflection, :class_name
3
+
4
+ delegate :foreign_type, :active_record, :to => :reflection
5
+
6
+ def self.call(reflection, name, class_name)
7
+ filter = new(reflection, class_name)
8
+ klass = reflection.class
9
+
10
+ if defined?(ActiveRecord::Reflection::MacroReflection)
11
+ klass.new name, filter.scope, filter.options, reflection.active_record
12
+ elsif reflection.respond_to?(:scope)
13
+ klass.new reflection.macro, name, filter.scope, filter.options,
14
+ reflection.active_record
15
+ else
16
+ klass.new reflection.macro, name, filter.options,
17
+ reflection.active_record
18
+ end
19
+ end
20
+
21
+ def initialize(reflection, class_name)
22
+ @reflection, @class_name = reflection, class_name
23
+ @options = reflection.options.clone
24
+ end
25
+
26
+ def options
27
+ @options.delete :polymorphic
28
+ @options[:class_name] = class_name
29
+ @options[:foreign_key] ||= "#{reflection.name}_id"
30
+ @options[:foreign_type] = reflection.foreign_type
31
+
32
+ if reflection.respond_to?(:scope)
33
+ @options[:sphinx_internal_filtered] = true
34
+ return @options
35
+ end
36
+
37
+ case @options[:conditions]
38
+ when nil
39
+ @options[:conditions] = condition
40
+ when Array
41
+ @options[:conditions] << condition
42
+ when Hash
43
+ @options[:conditions].merge!(reflection.foreign_type => @options[:class_name])
44
+ else
45
+ @options[:conditions] << " AND #{condition}"
46
+ end
47
+
48
+ @options
49
+ end
50
+
51
+ def scope
52
+ if ::Joiner::Joins.instance_methods.include?(:join_association_class)
53
+ return nil
54
+ end
55
+
56
+ lambda { |association|
57
+ reflection = association.reflection
58
+ klass = reflection.class_name.constantize
59
+ where(
60
+ association.parent.aliased_table_name.to_sym =>
61
+ {reflection.foreign_type => klass.base_class.name}
62
+ )
63
+ }
64
+ end
65
+
66
+ private
67
+
68
+ def condition
69
+ "::ts_join_alias::.#{quoted_foreign_type} = '#{class_name}'"
70
+ end
71
+
72
+ def quoted_foreign_type
73
+ active_record.connection.quote_column_name foreign_type
74
+ end
75
+ end
@@ -14,7 +14,7 @@ class ThinkingSphinx::ActiveRecord::Polymorpher
14
14
 
15
15
  def append_reflections
16
16
  mappings.each do |class_name, name|
17
- next if klass.reflections[name]
17
+ next if klass.reflect_on_association(name)
18
18
 
19
19
  reflection = clone_with name, class_name
20
20
  if ActiveRecord::Reflection.respond_to?(:add_reflection)
@@ -26,7 +26,7 @@ class ThinkingSphinx::ActiveRecord::Polymorpher
26
26
  end
27
27
 
28
28
  def clone_with(name, class_name)
29
- ThinkingSphinx::ActiveRecord::FilteredReflection.clone_with_filter(
29
+ ThinkingSphinx::ActiveRecord::FilterReflection.call(
30
30
  reflection, name, class_name
31
31
  )
32
32
  end
@@ -51,12 +51,12 @@ class ThinkingSphinx::ActiveRecord::Polymorpher
51
51
  end
52
52
 
53
53
  def reflection
54
- @reflection ||= klass.reflections[column.__name]
54
+ @reflection ||= klass.reflect_on_association column.__name
55
55
  end
56
56
 
57
57
  def klass
58
58
  @klass ||= column.__stack.inject(source.model) { |parent, key|
59
- parent.reflections[key].klass
59
+ parent.reflect_on_association(key).klass
60
60
  }
61
61
  end
62
62
  end
@@ -110,7 +110,7 @@ primary key.
110
110
  base = source.model
111
111
 
112
112
  column.__stack.collect { |key|
113
- reflection = base.reflections[key]
113
+ reflection = base.reflect_on_association key
114
114
  base = reflection.klass
115
115
 
116
116
  extend_reflection reflection
@@ -8,7 +8,7 @@ class ThinkingSphinx::ActiveRecord::SimpleManyQuery <
8
8
  private
9
9
 
10
10
  def reflection
11
- @reflection ||= source.model.reflections[column.__stack.first]
11
+ @reflection ||= source.model.reflect_on_association column.__stack.first
12
12
  end
13
13
 
14
14
  def quoted_foreign_key
@@ -100,10 +100,6 @@ module ThinkingSphinx
100
100
  "($id - #{source.offset}) / #{config.indices.count}"
101
101
  end
102
102
 
103
- def inheritance_column_condition
104
- "#{quoted_inheritance_column} = '#{model_name}'"
105
- end
106
-
107
103
  def range_condition
108
104
  condition = []
109
105
  condition << "#{quoted_primary_key} BETWEEN $start AND $end" unless source.disable_range?
@@ -129,7 +129,6 @@ module ThinkingSphinx
129
129
 
130
130
  def where_clause(for_range = false)
131
131
  builder = SQLBuilder::ClauseBuilder.new(nil)
132
- builder.add_clause inheritance_column_condition unless model.descends_from_active_record?
133
132
  builder.add_clause delta_processor.clause(source.delta?) if delta_processor
134
133
  builder.add_clause range_condition unless for_range
135
134
  builder.separated(' AND ')
@@ -3,7 +3,7 @@ require 'pathname'
3
3
  class ThinkingSphinx::Configuration < Riddle::Configuration
4
4
  attr_accessor :configuration_file, :indices_location, :version
5
5
  attr_reader :index_paths
6
- attr_writer :controller
6
+ attr_writer :controller, :index_set_class
7
7
 
8
8
  delegate :environment, :to => :framework
9
9
 
@@ -56,9 +56,12 @@ class ThinkingSphinx::Configuration < Riddle::Configuration
56
56
  end
57
57
  end
58
58
 
59
+ def index_set_class
60
+ @index_set_class ||= ThinkingSphinx::IndexSet
61
+ end
62
+
59
63
  def indices_for_references(*references)
60
- preload_indices
61
- indices.select { |index| references.include?(index.reference) }
64
+ index_set_class.new(:references => references).to_a
62
65
  end
63
66
 
64
67
  def next_offset(reference)
@@ -12,7 +12,7 @@ module ThinkingSphinx::Core::Index
12
12
  @docinfo = :extern
13
13
  @charset_type = 'utf-8'
14
14
  @options = options
15
- @offset = config.next_offset(reference)
15
+ @offset = config.next_offset(options[:offset_as] || reference)
16
16
  @type = 'plain'
17
17
 
18
18
  super "#{options[:name] || reference.to_s.gsub('/', '_')}_#{name_suffix}"
@@ -15,7 +15,10 @@ class ThinkingSphinx::Excerpter
15
15
 
16
16
  def excerpt!(text)
17
17
  result = ThinkingSphinx::Connection.take do |connection|
18
- connection.execute(statement_for(text)).first['snippet']
18
+ query = statement_for text
19
+ ThinkingSphinx::Logger.log :query, query do
20
+ connection.execute(query).first['snippet']
21
+ end
19
22
  end
20
23
 
21
24
  encoded? ? result : ThinkingSphinx::UTF8.encode(result)
@@ -63,6 +63,10 @@ class ThinkingSphinx::FacetSearch
63
63
 
64
64
  private
65
65
 
66
+ def configuration
67
+ ThinkingSphinx::Configuration.instance
68
+ end
69
+
66
70
  def facets
67
71
  @facets ||= properties.group_by(&:name).collect { |name, matches|
68
72
  ThinkingSphinx::Facet.new name, matches
@@ -92,11 +96,13 @@ class ThinkingSphinx::FacetSearch
92
96
  end
93
97
 
94
98
  def indices
95
- @indices ||= ThinkingSphinx::IndexSet.new options[:classes], options[:indices]
99
+ @indices ||= configuration.index_set_class.new(
100
+ options.slice(:classes, :indices)
101
+ )
96
102
  end
97
103
 
98
104
  def max_matches
99
- ThinkingSphinx::Configuration.instance.settings['max_matches'] || 1000
105
+ configuration.settings['max_matches'] || 1000
100
106
  end
101
107
 
102
108
  def limit
@@ -3,9 +3,9 @@ class ThinkingSphinx::IndexSet
3
3
 
4
4
  delegate :each, :empty?, :to => :indices
5
5
 
6
- def initialize(classes, index_names, configuration = nil)
7
- @classes = classes || []
8
- @index_names = index_names
6
+ def initialize(options = {}, configuration = nil)
7
+ @options = options
8
+ @index_names = options[:indices] || []
9
9
  @configuration = configuration || ThinkingSphinx::Configuration.instance
10
10
  end
11
11
 
@@ -19,7 +19,20 @@ class ThinkingSphinx::IndexSet
19
19
 
20
20
  private
21
21
 
22
- attr_reader :classes, :configuration, :index_names
22
+ attr_reader :configuration, :options
23
+
24
+ def all_indices
25
+ configuration.preload_indices
26
+ configuration.indices
27
+ end
28
+
29
+ def classes
30
+ options[:classes] || []
31
+ end
32
+
33
+ def classes_specified?
34
+ classes.any? || references_specified?
35
+ end
23
36
 
24
37
  def classes_and_ancestors
25
38
  @classes_and_ancestors ||= classes.collect { |model|
@@ -31,21 +44,30 @@ class ThinkingSphinx::IndexSet
31
44
  }.flatten
32
45
  end
33
46
 
34
- def indices
35
- configuration.preload_indices
47
+ def index_names
48
+ options[:indices] || []
49
+ end
36
50
 
37
- return configuration.indices.select { |index|
51
+ def indices
52
+ return all_indices.select { |index|
38
53
  index_names.include?(index.name)
39
- } if index_names && index_names.any?
54
+ } if index_names.any?
40
55
 
41
- everything = classes.empty? ? configuration.indices :
42
- configuration.indices_for_references(*references)
56
+ everything = classes_specified? ? indices_for_references : all_indices
43
57
  everything.reject &:distributed?
44
58
  end
45
59
 
60
+ def indices_for_references
61
+ all_indices.select { |index| references.include? index.reference }
62
+ end
63
+
46
64
  def references
47
- classes_and_ancestors.collect { |klass|
65
+ options[:references] || classes_and_ancestors.collect { |klass|
48
66
  klass.name.underscore.to_sym
49
67
  }
50
68
  end
69
+
70
+ def references_specified?
71
+ options[:references] && options[:references].any?
72
+ end
51
73
  end