@@ -43,17 +43,20 @@ def sets
4343 end
4444
4545 def find ( selector , options = { } )
46- return next_set ( options [ :resumption_token ] ) if options [ :resumption_token ]
46+ find_scope = find_scope ( options )
47+ return next_set ( find_scope ,
48+ options [ :resumption_token ] ) if options [ :resumption_token ]
4749 conditions = sql_conditions ( options )
4850 if :all == selector
49- total = model . count ( :id , :conditions => conditions )
51+ total = find_scope . count ( :id , :conditions => conditions )
5052 if @limit && total > @limit
51- select_partial ( ResumptionToken . new ( options . merge ( { :last => 0 } ) ) )
53+ select_partial ( find_scope ,
54+ ResumptionToken . new ( options . merge ( { :last => 0 } ) ) )
5255 else
53- model . find ( :all , :conditions => conditions )
56+ find_scope . find ( :all , :conditions => conditions )
5457 end
5558 else
56- model . find ( selector , :conditions => conditions )
59+ find_scope . find ( selector , :conditions => conditions )
5760 end
5861 end
5962
@@ -84,26 +87,58 @@ def method_missing(m, *args, &block)
8487
8588 protected
8689
90+ def find_scope ( options )
91+ return model unless options . key? ( :set )
92+
93+ # Find the set or return an empty scope
94+ set = find_set_by_spec ( options [ :set ] )
95+ return model . scoped ( :limit => 0 ) if set . nil?
96+
97+ # If the set has a backward relationship, we'll use it
98+ if set . class . respond_to? ( :reflect_on_all_associations )
99+ set . class . reflect_on_all_associations . each do |assoc |
100+ return set . send ( assoc . name ) . scoped if assoc . klass == model
101+ end
102+ end
103+
104+ # Search the attributes for 'set'
105+ if model . column_names . include? ( 'set' )
106+ # Scope using the set attribute as the spec
107+ model . scoped ( :conditions => { :set => options [ :set ] } )
108+ else
109+ # Default to empty set, as we've tried everything else
110+ model . scoped ( :limit => 0 )
111+ end
112+ end
113+
114+ def find_set_by_spec ( spec )
115+ if sets . class == ActiveRecord ::Relation
116+ sets . find_by_spec ( spec )
117+ else
118+ sets . detect { |set | set . spec == spec }
119+ end
120+ end
121+
87122 # Request the next set in this sequence.
88- def next_set ( token_string )
123+ def next_set ( find_scope , token_string )
89124 raise OAI ::ResumptionTokenException . new unless @limit
90125
91126 token = ResumptionToken . parse ( token_string )
92- total = model . count ( :id , :conditions => token_conditions ( token ) )
127+ total = find_scope . count ( :id , :conditions => token_conditions ( token ) )
93128
94129 if @limit < total
95- select_partial ( token )
130+ select_partial ( find_scope , token )
96131 else # end of result set
97- model . find ( :all ,
132+ find_scope . find ( :all ,
98133 :conditions => token_conditions ( token ) ,
99134 :limit => @limit , :order => "#{ model . primary_key } asc" )
100135 end
101136 end
102137
103138 # select a subset of the result set, and return it with a
104139 # resumption token to get the next subset
105- def select_partial ( token )
106- records = model . find ( :all ,
140+ def select_partial ( find_scope , token )
141+ records = find_scope . find ( :all ,
107142 :conditions => token_conditions ( token ) ,
108143 :limit => @limit ,
109144 :order => "#{ model . primary_key } asc" )
@@ -144,10 +179,6 @@ def sql_conditions(opts)
144179 sql << "#{ timestamp_field } < :until"
145180 esc_values [ :until ] = parse_to_local ( opts [ :until ] ) { |t | t + 1 }
146181 end
147- if opts . has_key? ( :set )
148- sql << "set = :set"
149- esc_values [ :set ] = opts [ :set ]
150- end
151182 return [ sql . join ( " AND " ) , esc_values ]
152183 end
153184
0 commit comments