model_set 0.11.1 → 1.0.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.
- data/Rakefile +2 -2
- data/VERSION +1 -0
- data/lib/model_set/conditioned.rb +1 -1
- data/lib/model_set/query.rb +7 -3
- data/lib/model_set/solr_query.rb +27 -20
- data/lib/model_set/sphinx_query.rb +4 -4
- data/lib/model_set/sql_query.rb +35 -16
- data/lib/model_set.rb +18 -1
- data/model_set.gemspec +107 -113
- data/test/model_set_test.rb +62 -40
- data/test/test_helper.rb +1 -0
- metadata +54 -26
- data/VERSION.yml +0 -5
data/Rakefile
CHANGED
@@ -11,8 +11,8 @@ begin
|
|
11
11
|
s.homepage = "http://github.com/ninjudd/model_set"
|
12
12
|
s.description = "Easy manipulation of sets of ActiveRecord models"
|
13
13
|
s.authors = ["Justin Balthrop"]
|
14
|
-
s.add_dependency('ordered_set', '>= 1.0.
|
15
|
-
s.add_dependency('deep_clonable', '>= 1.0
|
14
|
+
s.add_dependency('ordered_set', '>= 1.0.1')
|
15
|
+
s.add_dependency('deep_clonable', '>= 1.1.0')
|
16
16
|
s.add_dependency('activerecord', '>= 2.0.0')
|
17
17
|
end
|
18
18
|
Jeweler::GemcutterTasks.new
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
data/lib/model_set/query.rb
CHANGED
@@ -2,12 +2,12 @@ class ModelSet
|
|
2
2
|
class Query
|
3
3
|
deep_clonable
|
4
4
|
|
5
|
-
def initialize(model_set = ModelSet)
|
5
|
+
def initialize(model_set = ModelSet, *args)
|
6
6
|
if model_set.kind_of?(Class)
|
7
7
|
@set_class = model_set
|
8
8
|
else
|
9
9
|
@set_class = model_set.class
|
10
|
-
anchor!(model_set.query) if model_set.query
|
10
|
+
anchor!(model_set.query, *args) if model_set.query
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
@@ -57,7 +57,7 @@ class ModelSet
|
|
57
57
|
end
|
58
58
|
|
59
59
|
attr_reader :set_class
|
60
|
-
delegate :id_field, :
|
60
|
+
delegate :id_field, :to => :set_class
|
61
61
|
|
62
62
|
def model_class
|
63
63
|
set_class.query_model_class
|
@@ -71,6 +71,10 @@ class ModelSet
|
|
71
71
|
model_class.table_name
|
72
72
|
end
|
73
73
|
|
74
|
+
def id_field_with_prefix
|
75
|
+
"#{table_name}.#{id_field}"
|
76
|
+
end
|
77
|
+
|
74
78
|
attr_reader :limit, :sort_order
|
75
79
|
|
76
80
|
def offset
|
data/lib/model_set/solr_query.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
+
require 'solr'
|
2
|
+
|
1
3
|
class ModelSet
|
2
4
|
class SolrQuery < Query
|
5
|
+
attr_reader :response
|
3
6
|
include Conditioned
|
4
7
|
|
5
8
|
MAX_SOLR_RESULTS = 1000
|
@@ -23,37 +26,41 @@ class ModelSet
|
|
23
26
|
@ids
|
24
27
|
end
|
25
28
|
|
29
|
+
def config(params)
|
30
|
+
@config = @config ? @config.merge(params) : params
|
31
|
+
end
|
32
|
+
|
26
33
|
private
|
27
34
|
|
28
35
|
def fetch_results
|
29
|
-
query = "#{conditions.to_s}
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
+
query = "#{conditions.to_s}"
|
37
|
+
solr_params = {:highlighting => {}}
|
38
|
+
|
39
|
+
if set_class.respond_to?(:solr_field_list)
|
40
|
+
solr_params[:field_list] = set_class.solr_field_list
|
41
|
+
end
|
42
|
+
|
36
43
|
if limit
|
37
|
-
solr_params
|
38
|
-
solr_params
|
44
|
+
solr_params[:rows] = limit
|
45
|
+
solr_params[:start] = offset
|
39
46
|
else
|
40
|
-
solr_params
|
47
|
+
solr_params[:rows] = MAX_SOLR_RESULTS
|
41
48
|
end
|
42
|
-
|
43
|
-
solr_params = solr_params.join('&')
|
49
|
+
|
44
50
|
before_query(solr_params)
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
51
|
+
begin
|
52
|
+
solr_uri = "http://" + SOLR_HOST
|
53
|
+
if @config[:core]
|
54
|
+
solr_uri << "/" + @config[:core]
|
55
|
+
end
|
56
|
+
@response = Solr::Connection.new(solr_uri).search(query, solr_params)
|
49
57
|
rescue Exception => e
|
50
58
|
on_exception(e, solr_params)
|
51
59
|
end
|
52
|
-
|
53
60
|
after_query(solr_params)
|
54
|
-
|
55
|
-
@count =
|
56
|
-
@ids =
|
61
|
+
|
62
|
+
@count = @response.total_hits
|
63
|
+
@ids = @response.hits.map{ |hit| hit[@config[:response_id_field]].to_i }
|
57
64
|
@size = @ids.size
|
58
65
|
end
|
59
66
|
|
@@ -48,7 +48,7 @@ class ModelSet
|
|
48
48
|
conditions.each do |field, value|
|
49
49
|
next if value.nil?
|
50
50
|
field = field.join(',') if field.kind_of?(Array)
|
51
|
-
value = value.
|
51
|
+
value = "(#{value.join('|')})" if value.kind_of?(Array)
|
52
52
|
add_conditions!("@(#{field}) #{value}")
|
53
53
|
end
|
54
54
|
else
|
@@ -186,9 +186,9 @@ class ModelSet
|
|
186
186
|
def filter_values(values)
|
187
187
|
Array(values).collect do |value|
|
188
188
|
case value
|
189
|
-
when Date
|
190
|
-
when TrueClass
|
191
|
-
when FalseClass
|
189
|
+
when Date then value.to_time.to_i
|
190
|
+
when TrueClass then 1
|
191
|
+
when FalseClass then 0
|
192
192
|
else
|
193
193
|
value.to_i
|
194
194
|
end
|
data/lib/model_set/sql_query.rb
CHANGED
@@ -2,25 +2,44 @@ class ModelSet
|
|
2
2
|
class SQLQuery < SQLBaseQuery
|
3
3
|
include Conditioned
|
4
4
|
|
5
|
-
def anchor!(query)
|
6
|
-
if
|
7
|
-
|
5
|
+
def anchor!(query, opts = {})
|
6
|
+
if @limit_fetch = opts[:limit_fetch]
|
7
|
+
@reorder = query.ids
|
8
8
|
else
|
9
|
-
|
9
|
+
if query.respond_to?(:sql)
|
10
|
+
sql = "#{id_field_with_prefix} IN (#{query.sql})"
|
11
|
+
else
|
12
|
+
sql = ids_clause(query.ids)
|
13
|
+
@reorder = query.ids
|
14
|
+
end
|
15
|
+
add_conditions!(sql)
|
10
16
|
end
|
11
|
-
@reorder = query.ids
|
12
|
-
add_conditions!(sql)
|
13
17
|
end
|
14
|
-
|
18
|
+
|
15
19
|
def ids
|
16
20
|
if @ids.nil?
|
17
|
-
@
|
18
|
-
|
21
|
+
if @limit_fetch
|
22
|
+
base_conditions = conditions
|
23
|
+
@ids = [].to_ordered_set
|
24
|
+
@reorder.each_slice(@limit_fetch) do |ids|
|
25
|
+
self.conditions = Conditions.new(:and, ids_clause(ids), *base_conditions)
|
26
|
+
@ids.concat fetch_id_set(sql)
|
27
|
+
if limit and @ids.size >= limit
|
28
|
+
@ids.reorder!(@reorder).limit!(limit)
|
29
|
+
break
|
30
|
+
end
|
31
|
+
end
|
32
|
+
self.conditions = base_conditions
|
33
|
+
else
|
34
|
+
@ids = fetch_id_set(sql)
|
35
|
+
@ids.reorder!(@reorder) if @reorder
|
36
|
+
end
|
19
37
|
end
|
20
38
|
@ids
|
21
39
|
end
|
22
40
|
|
23
41
|
def limit_enabled?
|
42
|
+
return true if @limit_fetch
|
24
43
|
return false if @reorder
|
25
44
|
super
|
26
45
|
end
|
@@ -56,7 +75,7 @@ class ModelSet
|
|
56
75
|
@reorder = nil
|
57
76
|
clear_cache!
|
58
77
|
end
|
59
|
-
|
78
|
+
|
60
79
|
def reverse!
|
61
80
|
if @reorder
|
62
81
|
@reorder.reverse!
|
@@ -81,23 +100,23 @@ class ModelSet
|
|
81
100
|
def count
|
82
101
|
@count ||= limit ? aggregate("COUNT(DISTINCT #{id_field_with_prefix})").to_i : size
|
83
102
|
end
|
84
|
-
|
103
|
+
|
85
104
|
private
|
86
|
-
|
105
|
+
|
87
106
|
def select_clause
|
88
107
|
"SELECT #{id_field_with_prefix}"
|
89
108
|
end
|
90
|
-
|
109
|
+
|
91
110
|
def from_clause
|
92
111
|
"FROM #{table_name} #{join_clause} WHERE #{conditions.to_s}"
|
93
112
|
end
|
94
|
-
|
113
|
+
|
95
114
|
def order_clause
|
96
115
|
return unless @sort_order
|
97
116
|
# Prevent SQL injection attacks.
|
98
|
-
"ORDER BY #{@sort_order.join(', ').gsub(/[^\w_, \.\(\)'\"]/, '')}"
|
117
|
+
"ORDER BY #{@sort_order.join(', ').gsub(/[^\w_, \.\(\)\[\]'\"]/, '')}"
|
99
118
|
end
|
100
|
-
|
119
|
+
|
101
120
|
def join_clause
|
102
121
|
return unless @joins or @sort_join
|
103
122
|
joins = []
|
data/lib/model_set.rb
CHANGED
@@ -398,6 +398,11 @@ class ModelSet
|
|
398
398
|
end
|
399
399
|
end
|
400
400
|
|
401
|
+
clone_method :lazy_limit
|
402
|
+
def lazy_limit!(limit, fetch = limit * 10)
|
403
|
+
anchor!(:sql, :limit_fetch => fetch).limit!(limit)
|
404
|
+
end
|
405
|
+
|
401
406
|
def extract_opt(key, args)
|
402
407
|
opts = args.last.kind_of?(Hash) ? args.pop : {}
|
403
408
|
opt = opts.delete(key)
|
@@ -610,11 +615,15 @@ private
|
|
610
615
|
end
|
611
616
|
models.each do |model|
|
612
617
|
id = model.send(id_field)
|
613
|
-
models_by_id[id] ||= model
|
618
|
+
models_by_id[id] ||= after_fetch(model)
|
614
619
|
end
|
615
620
|
end
|
616
621
|
end
|
617
622
|
|
623
|
+
def after_fetch(model)
|
624
|
+
model
|
625
|
+
end
|
626
|
+
|
618
627
|
def as_id(model)
|
619
628
|
case model
|
620
629
|
when model_class
|
@@ -741,3 +750,11 @@ class ActiveRecord::Base
|
|
741
750
|
end
|
742
751
|
end
|
743
752
|
end
|
753
|
+
|
754
|
+
unless defined?(PGconn) and PGconn.respond_to?(:quote_ident)
|
755
|
+
class PGconn
|
756
|
+
def self.quote_ident(name)
|
757
|
+
%("#{name}")
|
758
|
+
end
|
759
|
+
end
|
760
|
+
end
|
data/model_set.gemspec
CHANGED
@@ -1,146 +1,140 @@
|
|
1
1
|
# Generated by jeweler
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{model_set}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "1.0.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Justin Balthrop"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2011-06-02}
|
13
13
|
s.description = %q{Easy manipulation of sets of ActiveRecord models}
|
14
14
|
s.email = %q{code@justinbalthrop.com}
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE",
|
17
|
-
|
17
|
+
"README.rdoc"
|
18
18
|
]
|
19
19
|
s.files = [
|
20
20
|
"LICENSE",
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
21
|
+
"README.rdoc",
|
22
|
+
"Rakefile",
|
23
|
+
"VERSION",
|
24
|
+
"lib/model_set.rb",
|
25
|
+
"lib/model_set/conditioned.rb",
|
26
|
+
"lib/model_set/conditions.rb",
|
27
|
+
"lib/model_set/query.rb",
|
28
|
+
"lib/model_set/raw_query.rb",
|
29
|
+
"lib/model_set/raw_sql_query.rb",
|
30
|
+
"lib/model_set/set_query.rb",
|
31
|
+
"lib/model_set/solr_query.rb",
|
32
|
+
"lib/model_set/sphinx_query.rb",
|
33
|
+
"lib/model_set/sql_base_query.rb",
|
34
|
+
"lib/model_set/sql_query.rb",
|
35
|
+
"lib/multi_set.rb",
|
36
|
+
"model_set.gemspec",
|
37
|
+
"test/model_set_test.rb",
|
38
|
+
"test/multi_set_test.rb",
|
39
|
+
"test/test_helper.rb",
|
40
|
+
"vendor/sphinx_client/README.rdoc",
|
41
|
+
"vendor/sphinx_client/Rakefile",
|
42
|
+
"vendor/sphinx_client/init.rb",
|
43
|
+
"vendor/sphinx_client/install.rb",
|
44
|
+
"vendor/sphinx_client/lib/sphinx.rb",
|
45
|
+
"vendor/sphinx_client/lib/sphinx/client.rb",
|
46
|
+
"vendor/sphinx_client/lib/sphinx/request.rb",
|
47
|
+
"vendor/sphinx_client/lib/sphinx/response.rb",
|
48
|
+
"vendor/sphinx_client/spec/client_response_spec.rb",
|
49
|
+
"vendor/sphinx_client/spec/client_spec.rb",
|
50
|
+
"vendor/sphinx_client/spec/fixtures/default_search.php",
|
51
|
+
"vendor/sphinx_client/spec/fixtures/default_search_index.php",
|
52
|
+
"vendor/sphinx_client/spec/fixtures/excerpt_custom.php",
|
53
|
+
"vendor/sphinx_client/spec/fixtures/excerpt_default.php",
|
54
|
+
"vendor/sphinx_client/spec/fixtures/excerpt_flags.php",
|
55
|
+
"vendor/sphinx_client/spec/fixtures/field_weights.php",
|
56
|
+
"vendor/sphinx_client/spec/fixtures/filter.php",
|
57
|
+
"vendor/sphinx_client/spec/fixtures/filter_exclude.php",
|
58
|
+
"vendor/sphinx_client/spec/fixtures/filter_float_range.php",
|
59
|
+
"vendor/sphinx_client/spec/fixtures/filter_float_range_exclude.php",
|
60
|
+
"vendor/sphinx_client/spec/fixtures/filter_range.php",
|
61
|
+
"vendor/sphinx_client/spec/fixtures/filter_range_exclude.php",
|
62
|
+
"vendor/sphinx_client/spec/fixtures/filter_range_int64.php",
|
63
|
+
"vendor/sphinx_client/spec/fixtures/filter_ranges.php",
|
64
|
+
"vendor/sphinx_client/spec/fixtures/filters.php",
|
65
|
+
"vendor/sphinx_client/spec/fixtures/filters_different.php",
|
66
|
+
"vendor/sphinx_client/spec/fixtures/geo_anchor.php",
|
67
|
+
"vendor/sphinx_client/spec/fixtures/group_by_attr.php",
|
68
|
+
"vendor/sphinx_client/spec/fixtures/group_by_attrpair.php",
|
69
|
+
"vendor/sphinx_client/spec/fixtures/group_by_day.php",
|
70
|
+
"vendor/sphinx_client/spec/fixtures/group_by_day_sort.php",
|
71
|
+
"vendor/sphinx_client/spec/fixtures/group_by_month.php",
|
72
|
+
"vendor/sphinx_client/spec/fixtures/group_by_week.php",
|
73
|
+
"vendor/sphinx_client/spec/fixtures/group_by_year.php",
|
74
|
+
"vendor/sphinx_client/spec/fixtures/group_distinct.php",
|
75
|
+
"vendor/sphinx_client/spec/fixtures/id_range.php",
|
76
|
+
"vendor/sphinx_client/spec/fixtures/id_range64.php",
|
77
|
+
"vendor/sphinx_client/spec/fixtures/index_weights.php",
|
78
|
+
"vendor/sphinx_client/spec/fixtures/keywords.php",
|
79
|
+
"vendor/sphinx_client/spec/fixtures/limits.php",
|
80
|
+
"vendor/sphinx_client/spec/fixtures/limits_cutoff.php",
|
81
|
+
"vendor/sphinx_client/spec/fixtures/limits_max.php",
|
82
|
+
"vendor/sphinx_client/spec/fixtures/limits_max_cutoff.php",
|
83
|
+
"vendor/sphinx_client/spec/fixtures/match_all.php",
|
84
|
+
"vendor/sphinx_client/spec/fixtures/match_any.php",
|
85
|
+
"vendor/sphinx_client/spec/fixtures/match_boolean.php",
|
86
|
+
"vendor/sphinx_client/spec/fixtures/match_extended.php",
|
87
|
+
"vendor/sphinx_client/spec/fixtures/match_extended2.php",
|
88
|
+
"vendor/sphinx_client/spec/fixtures/match_fullscan.php",
|
89
|
+
"vendor/sphinx_client/spec/fixtures/match_phrase.php",
|
90
|
+
"vendor/sphinx_client/spec/fixtures/max_query_time.php",
|
91
|
+
"vendor/sphinx_client/spec/fixtures/miltiple_queries.php",
|
92
|
+
"vendor/sphinx_client/spec/fixtures/ranking_bm25.php",
|
93
|
+
"vendor/sphinx_client/spec/fixtures/ranking_none.php",
|
94
|
+
"vendor/sphinx_client/spec/fixtures/ranking_proximity.php",
|
95
|
+
"vendor/sphinx_client/spec/fixtures/ranking_proximity_bm25.php",
|
96
|
+
"vendor/sphinx_client/spec/fixtures/ranking_wordcount.php",
|
97
|
+
"vendor/sphinx_client/spec/fixtures/retries.php",
|
98
|
+
"vendor/sphinx_client/spec/fixtures/retries_delay.php",
|
99
|
+
"vendor/sphinx_client/spec/fixtures/select.php",
|
100
|
+
"vendor/sphinx_client/spec/fixtures/set_override.php",
|
101
|
+
"vendor/sphinx_client/spec/fixtures/sort_attr_asc.php",
|
102
|
+
"vendor/sphinx_client/spec/fixtures/sort_attr_desc.php",
|
103
|
+
"vendor/sphinx_client/spec/fixtures/sort_expr.php",
|
104
|
+
"vendor/sphinx_client/spec/fixtures/sort_extended.php",
|
105
|
+
"vendor/sphinx_client/spec/fixtures/sort_relevance.php",
|
106
|
+
"vendor/sphinx_client/spec/fixtures/sort_time_segments.php",
|
107
|
+
"vendor/sphinx_client/spec/fixtures/sphinxapi.php",
|
108
|
+
"vendor/sphinx_client/spec/fixtures/update_attributes.php",
|
109
|
+
"vendor/sphinx_client/spec/fixtures/update_attributes_mva.php",
|
110
|
+
"vendor/sphinx_client/spec/fixtures/weights.php",
|
111
|
+
"vendor/sphinx_client/spec/sphinx/sphinx-id64.conf",
|
112
|
+
"vendor/sphinx_client/spec/sphinx/sphinx.conf",
|
113
|
+
"vendor/sphinx_client/spec/sphinx/sphinx_test.sql",
|
114
|
+
"vendor/sphinx_client/sphinx.yml.tpl",
|
115
|
+
"vendor/sphinx_client/tasks/sphinx.rake"
|
116
116
|
]
|
117
117
|
s.homepage = %q{http://github.com/ninjudd/model_set}
|
118
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
119
118
|
s.require_paths = ["lib"]
|
120
|
-
s.rubygems_version = %q{1.3.
|
119
|
+
s.rubygems_version = %q{1.3.7}
|
121
120
|
s.summary = %q{Easy manipulation of sets of ActiveRecord models}
|
122
|
-
s.test_files = [
|
123
|
-
"test/model_set_test.rb",
|
124
|
-
"test/multi_set_test.rb",
|
125
|
-
"test/test_helper.rb"
|
126
|
-
]
|
127
121
|
|
128
122
|
if s.respond_to? :specification_version then
|
129
123
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
130
124
|
s.specification_version = 3
|
131
125
|
|
132
|
-
if Gem::Version.new(Gem::
|
133
|
-
s.add_runtime_dependency(%q<ordered_set>, [">= 1.0.
|
134
|
-
s.add_runtime_dependency(%q<deep_clonable>, [">= 1.0
|
126
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
127
|
+
s.add_runtime_dependency(%q<ordered_set>, [">= 1.0.1"])
|
128
|
+
s.add_runtime_dependency(%q<deep_clonable>, [">= 1.1.0"])
|
135
129
|
s.add_runtime_dependency(%q<activerecord>, [">= 2.0.0"])
|
136
130
|
else
|
137
|
-
s.add_dependency(%q<ordered_set>, [">= 1.0.
|
138
|
-
s.add_dependency(%q<deep_clonable>, [">= 1.0
|
131
|
+
s.add_dependency(%q<ordered_set>, [">= 1.0.1"])
|
132
|
+
s.add_dependency(%q<deep_clonable>, [">= 1.1.0"])
|
139
133
|
s.add_dependency(%q<activerecord>, [">= 2.0.0"])
|
140
134
|
end
|
141
135
|
else
|
142
|
-
s.add_dependency(%q<ordered_set>, [">= 1.0.
|
143
|
-
s.add_dependency(%q<deep_clonable>, [">= 1.0
|
136
|
+
s.add_dependency(%q<ordered_set>, [">= 1.0.1"])
|
137
|
+
s.add_dependency(%q<deep_clonable>, [">= 1.1.0"])
|
144
138
|
s.add_dependency(%q<activerecord>, [">= 2.0.0"])
|
145
139
|
end
|
146
140
|
end
|
data/test/model_set_test.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/test_helper'
|
2
2
|
|
3
3
|
class ModelSetTest < Test::Unit::TestCase
|
4
|
-
class CreateTables < ActiveRecord::Migration
|
4
|
+
class CreateTables < ActiveRecord::Migration
|
5
5
|
def self.up
|
6
6
|
create_table :heroes do |t|
|
7
7
|
t.column :name, :string
|
@@ -49,7 +49,7 @@ class ModelSetTest < Test::Unit::TestCase
|
|
49
49
|
drop_table :robots
|
50
50
|
end
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
class Superpower < ActiveRecord::Base
|
54
54
|
end
|
55
55
|
|
@@ -71,13 +71,13 @@ class ModelSetTest < Test::Unit::TestCase
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
75
|
class HeroSet < ModelSet
|
76
76
|
constructor :with_universe
|
77
77
|
clone_method :with_universe
|
78
78
|
def with_universe!(universe)
|
79
79
|
add_conditions!("universe = '#{universe}'")
|
80
|
-
end
|
80
|
+
end
|
81
81
|
|
82
82
|
clone_method :add_birthday
|
83
83
|
def add_birthday!
|
@@ -90,18 +90,18 @@ class ModelSetTest < Test::Unit::TestCase
|
|
90
90
|
CreateTables.verbose = false
|
91
91
|
CreateTables.up
|
92
92
|
end
|
93
|
-
|
93
|
+
|
94
94
|
teardown do
|
95
95
|
CreateTables.down
|
96
96
|
end
|
97
|
-
|
97
|
+
|
98
98
|
should "construct a model set" do
|
99
99
|
captain = Hero.create(:name => 'Captain America', :universe => 'Marvel')
|
100
100
|
spidey = Hero.create(:name => 'Spider Man', :universe => 'Marvel')
|
101
101
|
batman = Hero.create(:name => 'Batman', :universe => 'D.C.' )
|
102
102
|
superman = Hero.create(:name => 'Superman', :universe => 'D.C.' )
|
103
103
|
ironman = Hero.create(:name => 'Iron Man', :universe => 'Marvel')
|
104
|
-
|
104
|
+
|
105
105
|
set = HeroSet.with_universe('Marvel')
|
106
106
|
assert_equal [captain.id, spidey.id, ironman.id], set.ids
|
107
107
|
end
|
@@ -123,10 +123,10 @@ class ModelSetTest < Test::Unit::TestCase
|
|
123
123
|
should "order and reverse set" do
|
124
124
|
captain = Hero.create(:name => 'Captain America', :universe => 'Marvel')
|
125
125
|
spidey = Hero.create(:name => 'Spider Man', :universe => 'Marvel')
|
126
|
-
wolverine = Hero.create(:name => 'Wolverine', :universe => 'Marvel'
|
127
|
-
phoenix = Hero.create(:name => 'Phoenix', :universe => 'Marvel'
|
126
|
+
wolverine = Hero.create(:name => 'Wolverine', :universe => 'Marvel')
|
127
|
+
phoenix = Hero.create(:name => 'Phoenix', :universe => 'Marvel')
|
128
128
|
ironman = Hero.create(:name => 'Iron Man', :universe => 'Marvel')
|
129
|
-
|
129
|
+
|
130
130
|
ids = [captain.id, ironman.id, phoenix.id, spidey.id, wolverine.id]
|
131
131
|
set = HeroSet.with_universe('Marvel')
|
132
132
|
|
@@ -154,59 +154,59 @@ class ModelSetTest < Test::Unit::TestCase
|
|
154
154
|
missing_id = 5555
|
155
155
|
spidey = Hero.create(:name => 'Spider Man', :universe => 'Marvel')
|
156
156
|
set = HeroSet.new([spidey.id, missing_id])
|
157
|
-
|
157
|
+
|
158
158
|
# Iterate through the profiles so the missing ones will be detected.
|
159
159
|
set.each {}
|
160
160
|
assert_equal [missing_id], set.missing_ids
|
161
161
|
end
|
162
|
-
|
162
|
+
|
163
163
|
should "have missing ids with add_fields" do
|
164
164
|
missing_id = 5555
|
165
165
|
spidey = Hero.create(:name => 'Spider Man', :universe => 'Marvel')
|
166
166
|
set = HeroSet.new([spidey.id, missing_id]).add_birthday
|
167
|
-
|
167
|
+
|
168
168
|
# Iterate through the profiles so the missing ones will be detected.
|
169
169
|
set.each {}
|
170
170
|
assert_equal [missing_id], set.missing_ids
|
171
171
|
end
|
172
|
-
|
172
|
+
|
173
173
|
should "support has_set" do
|
174
174
|
hero = Hero.create(:name => 'Mr. Invisible')
|
175
175
|
mighty_mouse = Superpet.create(:name => 'Mighty Mouse', :owner_id => hero.id)
|
176
176
|
underdog = Superpet.create(:name => 'Underdog', :owner_id => hero.id)
|
177
|
-
|
177
|
+
|
178
178
|
set = hero.pets
|
179
179
|
assert_equal SuperpetSet, set.class
|
180
180
|
assert_equal [mighty_mouse.id, underdog.id], set.ids
|
181
181
|
end
|
182
|
-
|
182
|
+
|
183
183
|
should "support has_set with through" do
|
184
184
|
hero = Hero.create(:name => 'Mr. Invisible')
|
185
185
|
invisibility = Superpower.create(:name => 'Invisibility')
|
186
186
|
flying = Superpower.create(:name => 'Flying')
|
187
187
|
HeroSuperpower.create(:hero_id => hero.id, :power_id => invisibility.id)
|
188
188
|
HeroSuperpower.create(:hero_id => hero.id, :power_id => flying.id)
|
189
|
-
|
189
|
+
|
190
190
|
set = hero.superpowers
|
191
191
|
assert_equal SuperpowerSet, set.class
|
192
192
|
assert_equal [invisibility.id, flying.id], set.ids
|
193
193
|
end
|
194
|
-
|
194
|
+
|
195
195
|
should "allow set extensions" do
|
196
196
|
hero = Hero.create(:name => 'Mr. Invisible')
|
197
197
|
mighty_mouse = Superpet.create(:name => 'Mighty Mouse', :owner_id => hero.id, :species => 'mouse')
|
198
198
|
sammy = Superpet.create(:name => 'Sammy Davis Jr. Jr.', :owner_id => hero.id, :species => 'dog')
|
199
199
|
underdog = Superpet.create(:name => 'Underdog', :owner_id => hero.id, :species => 'dog')
|
200
|
-
|
200
|
+
|
201
201
|
set = hero.pets
|
202
202
|
assert_equal ['mouse', 'dog', 'dog'], set.collect {|pet| pet.species}
|
203
|
-
|
203
|
+
|
204
204
|
assert_equal [sammy.id, underdog.id], set.dogs!.ids
|
205
205
|
end
|
206
206
|
|
207
207
|
class Robot < ActiveRecord::Base
|
208
208
|
end
|
209
|
-
|
209
|
+
|
210
210
|
class RobotSet < ModelSet
|
211
211
|
end
|
212
212
|
|
@@ -218,18 +218,18 @@ class ModelSetTest < Test::Unit::TestCase
|
|
218
218
|
@small_wonder = Robot.create(:name => 'Vicki', :classification => :child )
|
219
219
|
@t1000 = Robot.create(:name => 'Terminator', :classification => :assasin )
|
220
220
|
@johnny5 = Robot.create(:name => 'Johnny 5', :classification => :miltary )
|
221
|
-
|
221
|
+
|
222
222
|
@bot_set = RobotSet.new([@bender,@r2d2,@c3po,@rosie,@small_wonder,@t1000,@johnny5])
|
223
|
-
|
223
|
+
|
224
224
|
@data = Robot.create(:name => 'Data', :classification => :positronic)
|
225
225
|
@number8 = Robot.create(:name => 'Boomer', :classification => :cylon )
|
226
226
|
end
|
227
|
-
|
227
|
+
|
228
228
|
should "be empty" do
|
229
229
|
set = RobotSet.empty
|
230
230
|
assert_equal 0, set.size
|
231
231
|
assert set.empty?
|
232
|
-
|
232
|
+
|
233
233
|
set = RobotSet.new(@bender)
|
234
234
|
assert !set.empty?
|
235
235
|
end
|
@@ -248,13 +248,13 @@ class ModelSetTest < Test::Unit::TestCase
|
|
248
248
|
|
249
249
|
should "delete models from a set" do
|
250
250
|
set = RobotSet.new([@rosie, @small_wonder, @c3po])
|
251
|
-
|
251
|
+
|
252
252
|
set.delete(@c3po)
|
253
253
|
assert_equal [@rosie.id, @small_wonder.id], set.ids
|
254
|
-
|
254
|
+
|
255
255
|
set.delete(@rosie.id)
|
256
256
|
assert_equal [@small_wonder.id], set.ids
|
257
|
-
|
257
|
+
|
258
258
|
set.delete(@small_wonder)
|
259
259
|
assert_equal [], set.ids
|
260
260
|
assert set.empty?
|
@@ -263,26 +263,26 @@ class ModelSetTest < Test::Unit::TestCase
|
|
263
263
|
should "select models from a set" do
|
264
264
|
assert_equal [@r2d2, @c3po], @bot_set.select {|bot| bot.classification == :droid}.to_a
|
265
265
|
assert_equal 7, @bot_set.size
|
266
|
-
|
266
|
+
|
267
267
|
@bot_set.select! {|bot| bot.classification == :miltary}
|
268
|
-
assert_equal [@johnny5], @bot_set.to_a
|
268
|
+
assert_equal [@johnny5], @bot_set.to_a
|
269
269
|
end
|
270
|
-
|
270
|
+
|
271
271
|
should "sort a set" do
|
272
272
|
assert_equal [@bender,@c3po,@johnny5,@r2d2,@rosie,@t1000,@small_wonder], @bot_set.sort {|a,b| a.name <=> b.name}.to_a
|
273
273
|
assert_equal @johnny5, @bot_set.last
|
274
|
-
|
274
|
+
|
275
275
|
@bot_set.sort! {|a,b| b.name <=> a.name}
|
276
|
-
assert_equal [@bender,@c3po,@johnny5,@r2d2,@rosie,@t1000,@small_wonder].reverse, @bot_set.to_a
|
276
|
+
assert_equal [@bender,@c3po,@johnny5,@r2d2,@rosie,@t1000,@small_wonder].reverse, @bot_set.to_a
|
277
277
|
|
278
278
|
@bot_set.reverse!
|
279
|
-
assert_equal [@bender,@c3po,@johnny5,@r2d2,@rosie,@t1000,@small_wonder], @bot_set.to_a
|
279
|
+
assert_equal [@bender,@c3po,@johnny5,@r2d2,@rosie,@t1000,@small_wonder], @bot_set.to_a
|
280
280
|
end
|
281
|
-
|
281
|
+
|
282
282
|
should "sort a set by name" do
|
283
283
|
assert_equal [@bender,@c3po,@johnny5,@r2d2,@rosie,@t1000,@small_wonder], @bot_set.sort_by {|bot| bot.name}.to_a
|
284
284
|
end
|
285
|
-
|
285
|
+
|
286
286
|
should "reject models from a set" do
|
287
287
|
@bot_set.reject! {|bot| bot.classification == :domestic}
|
288
288
|
assert !@bot_set.include?(@rosie)
|
@@ -294,19 +294,19 @@ class ModelSetTest < Test::Unit::TestCase
|
|
294
294
|
humanoids = RobotSet.new([@small_wonder, @t1000, @data, @number8])
|
295
295
|
metalics = RobotSet.new([@r2d2, @c3po, @johnny5])
|
296
296
|
cartoons = RobotSet.new([@bender, @rosie])
|
297
|
-
|
297
|
+
|
298
298
|
assert_equal ['C3PO', 'R2D2', 'Johnny 5'], (droids + metalics).collect {|bot| bot.name}
|
299
299
|
assert_equal ['Bender', 'Rosie', 'C3PO', 'R2D2', 'Johnny 5'], (cartoons + droids + metalics).collect {|bot| bot.name}
|
300
300
|
assert_equal 5, (cartoons + droids + metalics).size
|
301
301
|
assert_equal 5, (cartoons + droids + metalics).count
|
302
|
-
|
302
|
+
|
303
303
|
assert_equal [], (droids - metalics).collect {|bot| bot.name}
|
304
304
|
assert_equal ['Johnny 5'], (metalics - droids).collect {|bot| bot.name}
|
305
305
|
assert_equal ['Terminator', 'Data'], (humanoids - womanoids).collect {|bot| bot.name}
|
306
306
|
assert_equal ['Bender'], (cartoons - womanoids).collect {|bot| bot.name}
|
307
307
|
assert_equal 2, (humanoids - womanoids).size
|
308
308
|
assert_equal 2, (humanoids - womanoids).count
|
309
|
-
|
309
|
+
|
310
310
|
assert_equal ['C3PO', 'R2D2'], (droids & metalics).collect {|bot| bot.name}
|
311
311
|
assert_equal ['R2D2', 'C3PO'], (metalics & droids).collect {|bot| bot.name}
|
312
312
|
assert_equal ['Vicki', 'Boomer'], (humanoids & womanoids).collect {|bot| bot.name}
|
@@ -319,11 +319,33 @@ class ModelSetTest < Test::Unit::TestCase
|
|
319
319
|
set -= @r2d2
|
320
320
|
assert_equal ['C3PO', 'Johnny 5'], set.collect {|bot| bot.name}
|
321
321
|
end
|
322
|
-
|
322
|
+
|
323
323
|
should "clone a set" do
|
324
324
|
set = RobotSet.new([1])
|
325
325
|
new_set = set.clone
|
326
326
|
assert new_set.object_id != set.object_id
|
327
327
|
end
|
328
|
+
|
329
|
+
should "limit lazily" do
|
330
|
+
captain = Hero.create(:name => 'Captain America', :universe => 'Marvel')
|
331
|
+
spidey = Hero.create(:name => 'Spider Man', :universe => 'Marvel')
|
332
|
+
wolverine = Hero.create(:name => 'Wolverine', :universe => 'Marvel')
|
333
|
+
phoenix = Hero.create(:name => 'Phoenix', :universe => 'Marvel')
|
334
|
+
ironman = Hero.create(:name => 'Iron Man', :universe => 'Marvel')
|
335
|
+
zombie = Hero.create(:name => 'Zombie 1', :universe => 'Zombie')
|
336
|
+
batman = Hero.create(:name => 'Batman', :universe => 'D.C.' )
|
337
|
+
superman = Hero.create(:name => 'Superman', :universe => 'D.C.' )
|
338
|
+
ryu = Hero.create(:name => 'Ryu', :universe => 'Capcom')
|
339
|
+
ken = Hero.create(:name => 'Ryu', :universe => 'Capcom')
|
340
|
+
zangief = Hero.create(:name => 'Zangief', :universe => 'Capcom')
|
341
|
+
blanka = Hero.create(:name => 'Blanka', :universe => 'Capcom')
|
342
|
+
|
343
|
+
ids = [superman.id, phoenix.id, zangief.id, captain.id, ryu.id, zombie.id, batman.id, blanka.id, spidey.id, ken.id]
|
344
|
+
|
345
|
+
s = HeroSet.new(ids)
|
346
|
+
s.lazy_limit!(3, 3).add_conditions!(:universe => 'Capcom')
|
347
|
+
|
348
|
+
assert_equal [zangief.id, ryu.id, blanka.id], s.ids
|
349
|
+
end
|
328
350
|
end
|
329
351
|
end
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: model_set
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 23
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 1.0.0
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Justin Balthrop
|
@@ -9,39 +15,57 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date:
|
18
|
+
date: 2011-06-02 00:00:00 -07:00
|
13
19
|
default_executable:
|
14
20
|
dependencies:
|
15
21
|
- !ruby/object:Gem::Dependency
|
16
22
|
name: ordered_set
|
17
|
-
|
18
|
-
|
19
|
-
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
20
26
|
requirements:
|
21
27
|
- - ">="
|
22
28
|
- !ruby/object:Gem::Version
|
23
|
-
|
24
|
-
|
29
|
+
hash: 21
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 0
|
33
|
+
- 1
|
34
|
+
version: 1.0.1
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
25
37
|
- !ruby/object:Gem::Dependency
|
26
38
|
name: deep_clonable
|
27
|
-
|
28
|
-
|
29
|
-
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
30
42
|
requirements:
|
31
43
|
- - ">="
|
32
44
|
- !ruby/object:Gem::Version
|
33
|
-
|
34
|
-
|
45
|
+
hash: 19
|
46
|
+
segments:
|
47
|
+
- 1
|
48
|
+
- 1
|
49
|
+
- 0
|
50
|
+
version: 1.1.0
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
35
53
|
- !ruby/object:Gem::Dependency
|
36
54
|
name: activerecord
|
37
|
-
|
38
|
-
|
39
|
-
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
40
58
|
requirements:
|
41
59
|
- - ">="
|
42
60
|
- !ruby/object:Gem::Version
|
61
|
+
hash: 15
|
62
|
+
segments:
|
63
|
+
- 2
|
64
|
+
- 0
|
65
|
+
- 0
|
43
66
|
version: 2.0.0
|
44
|
-
|
67
|
+
type: :runtime
|
68
|
+
version_requirements: *id003
|
45
69
|
description: Easy manipulation of sets of ActiveRecord models
|
46
70
|
email: code@justinbalthrop.com
|
47
71
|
executables: []
|
@@ -55,7 +79,7 @@ files:
|
|
55
79
|
- LICENSE
|
56
80
|
- README.rdoc
|
57
81
|
- Rakefile
|
58
|
-
- VERSION
|
82
|
+
- VERSION
|
59
83
|
- lib/model_set.rb
|
60
84
|
- lib/model_set/conditioned.rb
|
61
85
|
- lib/model_set/conditions.rb
|
@@ -153,30 +177,34 @@ homepage: http://github.com/ninjudd/model_set
|
|
153
177
|
licenses: []
|
154
178
|
|
155
179
|
post_install_message:
|
156
|
-
rdoc_options:
|
157
|
-
|
180
|
+
rdoc_options: []
|
181
|
+
|
158
182
|
require_paths:
|
159
183
|
- lib
|
160
184
|
required_ruby_version: !ruby/object:Gem::Requirement
|
185
|
+
none: false
|
161
186
|
requirements:
|
162
187
|
- - ">="
|
163
188
|
- !ruby/object:Gem::Version
|
189
|
+
hash: 3
|
190
|
+
segments:
|
191
|
+
- 0
|
164
192
|
version: "0"
|
165
|
-
version:
|
166
193
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
194
|
+
none: false
|
167
195
|
requirements:
|
168
196
|
- - ">="
|
169
197
|
- !ruby/object:Gem::Version
|
198
|
+
hash: 3
|
199
|
+
segments:
|
200
|
+
- 0
|
170
201
|
version: "0"
|
171
|
-
version:
|
172
202
|
requirements: []
|
173
203
|
|
174
204
|
rubyforge_project:
|
175
|
-
rubygems_version: 1.3.
|
205
|
+
rubygems_version: 1.3.7
|
176
206
|
signing_key:
|
177
207
|
specification_version: 3
|
178
208
|
summary: Easy manipulation of sets of ActiveRecord models
|
179
|
-
test_files:
|
180
|
-
|
181
|
-
- test/multi_set_test.rb
|
182
|
-
- test/test_helper.rb
|
209
|
+
test_files: []
|
210
|
+
|