acts_as_saveable 0.10.1
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.
- checksums.yaml +7 -0
- data/.gitignore +6 -0
- data/.travis.yml +25 -0
- data/Gemfile +17 -0
- data/README.markdown +399 -0
- data/Rakefile +10 -0
- data/acts_as_saveable.gemspec +24 -0
- data/lib/acts_as_saveable.rb +21 -0
- data/lib/acts_as_saveable/extenders/controller.rb +19 -0
- data/lib/acts_as_saveable/extenders/saveable.rb +25 -0
- data/lib/acts_as_saveable/extenders/saver.rb +24 -0
- data/lib/acts_as_saveable/helpers/words.rb +36 -0
- data/lib/acts_as_saveable/save.rb +28 -0
- data/lib/acts_as_saveable/saveable.rb +330 -0
- data/lib/acts_as_saveable/saver.rb +131 -0
- data/lib/acts_as_saveable/version.rb +3 -0
- data/lib/generators/acts_as_saveable/migration/migration_generator.rb +31 -0
- data/lib/generators/acts_as_saveable/migration/templates/active_record/migration.rb +27 -0
- data/spec/saveable_saver_spec.rb +21 -0
- data/spec/saveable_spec.rb +21 -0
- data/spec/saver_spec.rb +21 -0
- data/spec/shared_example/saveable_model_spec.rb +484 -0
- data/spec/shared_example/saver_model_spec.rb +275 -0
- data/spec/spec_helper.rb +132 -0
- data/spec/words_spec.rb +30 -0
- metadata +103 -0
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "acts_as_saveable/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "acts_as_saveable"
|
7
|
+
s.version = ActsAsSaveable::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Ali Ibrahim"]
|
10
|
+
s.email = ["aliibrahim@gmail.com"]
|
11
|
+
s.homepage = "http://rubygems.org/gems/acts_as_saveable"
|
12
|
+
s.summary = %q{Rails gem to allowing records to be saveable}
|
13
|
+
s.description = %q{Rails gem to allowing records to be saveable}
|
14
|
+
|
15
|
+
s.rubyforge_project = "acts_as_saveable"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.add_development_dependency "rspec"
|
23
|
+
s.add_development_dependency "sqlite3", '~> 1.3.9'
|
24
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'active_support/inflector'
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
5
|
+
|
6
|
+
module ActsAsSaveable
|
7
|
+
|
8
|
+
if defined?(ActiveRecord::Base)
|
9
|
+
require 'acts_as_saveable/extenders/saveable'
|
10
|
+
require 'acts_as_saveable/extenders/saver'
|
11
|
+
require 'acts_as_saveable/save'
|
12
|
+
ActiveRecord::Base.extend ActsAsSaveable::Extenders::Saveable
|
13
|
+
ActiveRecord::Base.extend ActsAsSaveable::Extenders::Saver
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
require 'acts_as_saveable/extenders/controller'
|
19
|
+
ActiveSupport.on_load(:action_controller) do
|
20
|
+
include ActsAsSaveable::Extenders::Controller
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ActsAsSaveable
|
2
|
+
module Extenders
|
3
|
+
|
4
|
+
module Controller
|
5
|
+
|
6
|
+
def saver_params(params_object = params[:saved])
|
7
|
+
params_object.permit(:saveable_id, :saveable_type,
|
8
|
+
:saver_id, :saver_type,
|
9
|
+
:saveable, :saver,
|
10
|
+
:save_flag, :save_scope)
|
11
|
+
end
|
12
|
+
|
13
|
+
def saveable_params(params_object = params[:saved])
|
14
|
+
params_object.permit(:save_registered)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ActsAsSaveable
|
2
|
+
module Extenders
|
3
|
+
|
4
|
+
module Saveable
|
5
|
+
|
6
|
+
def saveable?
|
7
|
+
false
|
8
|
+
end
|
9
|
+
|
10
|
+
def acts_as_saveable
|
11
|
+
require 'acts_as_saveable/saveable'
|
12
|
+
include ActsAsSaveable::Saveable
|
13
|
+
|
14
|
+
class_eval do
|
15
|
+
def self.saveable?
|
16
|
+
true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module ActsAsSaveable
|
2
|
+
module Extenders
|
3
|
+
|
4
|
+
module Saver
|
5
|
+
|
6
|
+
def saver?
|
7
|
+
false
|
8
|
+
end
|
9
|
+
|
10
|
+
def acts_as_saver(*args)
|
11
|
+
require 'acts_as_saveable/saver'
|
12
|
+
include ActsAsSaveable::Saver
|
13
|
+
|
14
|
+
class_eval do
|
15
|
+
def self.saver?
|
16
|
+
true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module ActsAsSaveable::Helpers
|
2
|
+
|
3
|
+
# this helper provides methods that help find what words are
|
4
|
+
# up saves and what words are down saves
|
5
|
+
#
|
6
|
+
# It can be called
|
7
|
+
#
|
8
|
+
# saveable_object.saveable_words.that_mean_true
|
9
|
+
#
|
10
|
+
module Words
|
11
|
+
|
12
|
+
def saveable_words
|
13
|
+
SaveableWords
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
class SaveableWords
|
19
|
+
|
20
|
+
def self.that_mean_true
|
21
|
+
['up', 'upsaved', 'like', 'liked', 'positive', 'yes', 'good', 'true', 1, true]
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.that_mean_false
|
25
|
+
['down', 'downsaved', 'dislike', 'disliked', 'negative', 'no', 'bad', 'false', 0, false]
|
26
|
+
end
|
27
|
+
|
28
|
+
# check is word is a true or bad saved
|
29
|
+
# if the word is unknown, then it counts it as a true/good
|
30
|
+
# saved. this exists to allow all saving to be good by default
|
31
|
+
def self.meaning_of word
|
32
|
+
!that_mean_false.include?(word)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'acts_as_saveable/helpers/words'
|
2
|
+
|
3
|
+
module ActsAsSaveable
|
4
|
+
class Save < ::ActiveRecord::Base
|
5
|
+
|
6
|
+
include Helpers::Words
|
7
|
+
|
8
|
+
if defined?(ProtectedAttributes) || ::ActiveRecord::VERSION::MAJOR < 4
|
9
|
+
attr_accessible :saveable_id, :saveable_type,
|
10
|
+
:saver_id, :saver_type,
|
11
|
+
:saveable, :saver,
|
12
|
+
:save_flag, :save_scope
|
13
|
+
end
|
14
|
+
|
15
|
+
belongs_to :saveable, :polymorphic => true
|
16
|
+
belongs_to :saver, :polymorphic => true
|
17
|
+
|
18
|
+
scope :up, lambda{ where(:save_flag => true) }
|
19
|
+
scope :down, lambda{ where(:save_flag => false) }
|
20
|
+
scope :for_type, lambda{ |klass| where(:saveable_type => klass) }
|
21
|
+
scope :by_type, lambda{ |klass| where(:saver_type => klass) }
|
22
|
+
|
23
|
+
validates_presence_of :saveable_id
|
24
|
+
validates_presence_of :saver_id
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,330 @@
|
|
1
|
+
require 'acts_as_saveable/helpers/words'
|
2
|
+
|
3
|
+
module ActsAsSaveable
|
4
|
+
module Saveable
|
5
|
+
|
6
|
+
include Helpers::Words
|
7
|
+
|
8
|
+
def self.included base
|
9
|
+
|
10
|
+
# allow the user to define these himself
|
11
|
+
aliases = {
|
12
|
+
|
13
|
+
:save_up => [
|
14
|
+
:upsaved_by, :upsave_from, :upsave_by, :save_from
|
15
|
+
],
|
16
|
+
|
17
|
+
:save_down => [
|
18
|
+
:downsave_by, :downsave_from, :downsaved_by, :downsave_from
|
19
|
+
],
|
20
|
+
|
21
|
+
:get_up_saves => [
|
22
|
+
:get_true_saves, :get_upsaves, :get_for_saves
|
23
|
+
],
|
24
|
+
|
25
|
+
:get_down_saves => [
|
26
|
+
:get_false_saves, :get_downsaves
|
27
|
+
],
|
28
|
+
:unsave_by => [
|
29
|
+
:unsave_up, :unsave_down
|
30
|
+
]
|
31
|
+
}
|
32
|
+
|
33
|
+
base.class_eval do
|
34
|
+
has_many :saves_for, :class_name => 'ActsAsSaveable::Save', :as => :saveable, :dependent => :destroy do
|
35
|
+
def savers
|
36
|
+
includes(:saver).map(&:saver)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
aliases.each do |method, links|
|
41
|
+
links.each do |new_method|
|
42
|
+
alias_method(new_method, method)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
attr_accessor :save_registered
|
50
|
+
|
51
|
+
def save_registered?
|
52
|
+
return self.save_registered
|
53
|
+
end
|
54
|
+
|
55
|
+
def default_conditions
|
56
|
+
{
|
57
|
+
:saveable_id => self.id,
|
58
|
+
:saveable_type => self.class.base_class.name.to_s
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
# saving
|
63
|
+
def save_by args = {}
|
64
|
+
|
65
|
+
options = {
|
66
|
+
:saved => true,
|
67
|
+
:save_scope => nil
|
68
|
+
}.merge(args)
|
69
|
+
|
70
|
+
self.save_registered = false
|
71
|
+
|
72
|
+
if options[:saver].nil?
|
73
|
+
return false
|
74
|
+
end
|
75
|
+
|
76
|
+
# find the saved
|
77
|
+
_saves_ = find_saves_for({
|
78
|
+
:saver_id => options[:saver].id,
|
79
|
+
:save_scope => options[:save_scope],
|
80
|
+
:saver_type => options[:saver].class.base_class.name
|
81
|
+
})
|
82
|
+
|
83
|
+
if _saves_.count == 0 or options[:duplicate]
|
84
|
+
# this saver has never saved
|
85
|
+
saved = ActsAsSaveable::Save.new(
|
86
|
+
:saveable => self,
|
87
|
+
:saver => options[:saver],
|
88
|
+
:save_scope => options[:save_scope]
|
89
|
+
)
|
90
|
+
else
|
91
|
+
# this saver is potentially changing his saved
|
92
|
+
saved = _saves_.last
|
93
|
+
end
|
94
|
+
|
95
|
+
last_update = saved.updated_at
|
96
|
+
|
97
|
+
saved.save_flag = saveable_words.meaning_of(options[:saved])
|
98
|
+
|
99
|
+
#Allowing for a save_weight to be associated with every saved. Could change with every saver object
|
100
|
+
saved.save_weight = (options[:save_weight].to_i if options[:save_weight].present?) || 1
|
101
|
+
|
102
|
+
if saved.save
|
103
|
+
self.save_registered = true if last_update != saved.updated_at
|
104
|
+
update_cached_saves options[:save_scope]
|
105
|
+
return true
|
106
|
+
else
|
107
|
+
self.save_registered = false
|
108
|
+
return false
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
def unsaved args = {}
|
114
|
+
return false if args[:saver].nil?
|
115
|
+
_saves_ = find_saves_for(:saver_id => args[:saver].id, :save_scope => args[:save_scope], :saver_type => args[:saver].class.base_class.name)
|
116
|
+
|
117
|
+
return true if _saves_.size == 0
|
118
|
+
_saves_.each(&:destroy)
|
119
|
+
update_cached_saves args[:save_scope]
|
120
|
+
self.save_registered = false if saves_for.count == 0
|
121
|
+
return true
|
122
|
+
end
|
123
|
+
|
124
|
+
def save_up saver, options={}
|
125
|
+
self.save_by :saver => saver, :saved => true, :save_scope => options[:save_scope], :save_weight => options[:save_weight]
|
126
|
+
end
|
127
|
+
|
128
|
+
def save_down saver, options={}
|
129
|
+
self.save_by :saver => saver, :saved => false, :save_scope => options[:save_scope], :save_weight => options[:save_weight]
|
130
|
+
end
|
131
|
+
|
132
|
+
def unsave_by saver, options = {}
|
133
|
+
self.unsaved :saver => saver, :save_scope => options[:save_scope] #Does not need save_weight since the saves_for are anyway getting destroyed
|
134
|
+
end
|
135
|
+
|
136
|
+
def scope_cache_field field, save_scope
|
137
|
+
return field if save_scope.nil?
|
138
|
+
|
139
|
+
case field
|
140
|
+
when :cached_saves_total=
|
141
|
+
"cached_scoped_#{save_scope}_saves_total="
|
142
|
+
when :cached_saves_total
|
143
|
+
"cached_scoped_#{save_scope}_saves_total"
|
144
|
+
when :cached_saves_up=
|
145
|
+
"cached_scoped_#{save_scope}_saves_up="
|
146
|
+
when :cached_saves_up
|
147
|
+
"cached_scoped_#{save_scope}_saves_up"
|
148
|
+
when :cached_saves_down=
|
149
|
+
"cached_scoped_#{save_scope}_saves_down="
|
150
|
+
when :cached_saves_down
|
151
|
+
"cached_scoped_#{save_scope}_saves_down"
|
152
|
+
when :cached_saves_score=
|
153
|
+
"cached_scoped_#{save_scope}_saves_score="
|
154
|
+
when :cached_saves_score
|
155
|
+
"cached_scoped_#{save_scope}_saves_score"
|
156
|
+
when :cached_weighted_total
|
157
|
+
"cached_weighted_#{save_scope}_total"
|
158
|
+
when :cached_weighted_total=
|
159
|
+
"cached_weighted_#{save_scope}_total="
|
160
|
+
when :cached_weighted_score
|
161
|
+
"cached_weighted_#{save_scope}_score"
|
162
|
+
when :cached_weighted_score=
|
163
|
+
"cached_weighted_#{save_scope}_score="
|
164
|
+
when :cached_weighted_average
|
165
|
+
"cached_weighted_#{save_scope}_average"
|
166
|
+
when :cached_weighted_average=
|
167
|
+
"cached_weighted_#{save_scope}_average="
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# caching
|
172
|
+
def update_cached_saves save_scope = nil
|
173
|
+
|
174
|
+
updates = {}
|
175
|
+
|
176
|
+
if self.respond_to?(:cached_saves_total=)
|
177
|
+
updates[:cached_saves_total] = count_saves_total(true)
|
178
|
+
end
|
179
|
+
|
180
|
+
if self.respond_to?(:cached_saves_up=)
|
181
|
+
updates[:cached_saves_up] = count_saves_up(true)
|
182
|
+
end
|
183
|
+
|
184
|
+
if self.respond_to?(:cached_saves_down=)
|
185
|
+
updates[:cached_saves_down] = count_saves_down(true)
|
186
|
+
end
|
187
|
+
|
188
|
+
if self.respond_to?(:cached_saves_score=)
|
189
|
+
updates[:cached_saves_score] = (
|
190
|
+
(updates[:cached_saves_up] || count_saves_up(true)) -
|
191
|
+
(updates[:cached_saves_down] || count_saves_down(true))
|
192
|
+
)
|
193
|
+
end
|
194
|
+
|
195
|
+
if self.respond_to?(:cached_weighted_total=)
|
196
|
+
updates[:cached_weighted_total] = weighted_total(true)
|
197
|
+
end
|
198
|
+
|
199
|
+
if self.respond_to?(:cached_weighted_score=)
|
200
|
+
updates[:cached_weighted_score] = weighted_score(true)
|
201
|
+
end
|
202
|
+
|
203
|
+
if self.respond_to?(:cached_weighted_average=)
|
204
|
+
updates[:cached_weighted_average] = weighted_average(true)
|
205
|
+
end
|
206
|
+
|
207
|
+
if save_scope
|
208
|
+
if self.respond_to?(scope_cache_field :cached_saves_total=, save_scope)
|
209
|
+
updates[scope_cache_field :cached_saves_total, save_scope] = count_saves_total(true, save_scope)
|
210
|
+
end
|
211
|
+
|
212
|
+
if self.respond_to?(scope_cache_field :cached_saves_up=, save_scope)
|
213
|
+
updates[scope_cache_field :cached_saves_up, save_scope] = count_saves_up(true, save_scope)
|
214
|
+
end
|
215
|
+
|
216
|
+
if self.respond_to?(scope_cache_field :cached_saves_down=, save_scope)
|
217
|
+
updates[scope_cache_field :cached_saves_down, save_scope] = count_saves_down(true, save_scope)
|
218
|
+
end
|
219
|
+
|
220
|
+
if self.respond_to?(scope_cache_field :cached_weighted_total=, save_scope)
|
221
|
+
updates[scope_cache_field :cached_weighted_total, save_scope] = weighted_total(true, save_scope)
|
222
|
+
end
|
223
|
+
|
224
|
+
if self.respond_to?(scope_cache_field :cached_weighted_score=, save_scope)
|
225
|
+
updates[scope_cache_field :cached_weighted_score, save_scope] = weighted_score(true, save_scope)
|
226
|
+
end
|
227
|
+
|
228
|
+
if self.respond_to?(scope_cache_field :cached_saves_score=, save_scope)
|
229
|
+
updates[scope_cache_field :cached_saves_score, save_scope] = (
|
230
|
+
(updates[scope_cache_field :cached_saves_up, save_scope] || count_saves_up(true, save_scope)) -
|
231
|
+
(updates[scope_cache_field :cached_saves_down, save_scope] || count_saves_down(true, save_scope))
|
232
|
+
)
|
233
|
+
end
|
234
|
+
|
235
|
+
if self.respond_to?(scope_cache_field :cached_weighted_average=, save_scope)
|
236
|
+
updates[scope_cache_field :cached_weighted_average, save_scope] = weighted_average(true, save_scope)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
if (::ActiveRecord::VERSION::MAJOR == 3) && (::ActiveRecord::VERSION::MINOR != 0)
|
241
|
+
self.update_attributes(updates, :without_protection => true) if updates.size > 0
|
242
|
+
else
|
243
|
+
self.update_attributes(updates) if updates.size > 0
|
244
|
+
end
|
245
|
+
|
246
|
+
end
|
247
|
+
|
248
|
+
|
249
|
+
# results
|
250
|
+
def find_saves_for extra_conditions = {}
|
251
|
+
saves_for.where(extra_conditions)
|
252
|
+
end
|
253
|
+
|
254
|
+
def get_up_saves options={}
|
255
|
+
save_scope_hash = scope_or_empty_hash(options[:save_scope])
|
256
|
+
find_saves_for({:save_flag => true}.merge(save_scope_hash))
|
257
|
+
end
|
258
|
+
|
259
|
+
def get_down_saves options={}
|
260
|
+
save_scope_hash = scope_or_empty_hash(options[:save_scope])
|
261
|
+
find_saves_for({:save_flag => false}.merge(save_scope_hash))
|
262
|
+
end
|
263
|
+
|
264
|
+
|
265
|
+
# counting
|
266
|
+
def count_saves_total skip_cache = false, save_scope = nil
|
267
|
+
if !skip_cache && self.respond_to?(scope_cache_field :cached_saves_total, save_scope)
|
268
|
+
return self.send(scope_cache_field :cached_saves_total, save_scope)
|
269
|
+
end
|
270
|
+
find_saves_for(scope_or_empty_hash(save_scope)).count
|
271
|
+
end
|
272
|
+
|
273
|
+
def count_saves_up skip_cache = false, save_scope = nil
|
274
|
+
if !skip_cache && self.respond_to?(scope_cache_field :cached_saves_up, save_scope)
|
275
|
+
return self.send(scope_cache_field :cached_saves_up, save_scope)
|
276
|
+
end
|
277
|
+
get_up_saves(:save_scope => save_scope).count
|
278
|
+
end
|
279
|
+
|
280
|
+
def count_saves_down skip_cache = false, save_scope = nil
|
281
|
+
if !skip_cache && self.respond_to?(scope_cache_field :cached_saves_down, save_scope)
|
282
|
+
return self.send(scope_cache_field :cached_saves_down, save_scope)
|
283
|
+
end
|
284
|
+
get_down_saves(:save_scope => save_scope).count
|
285
|
+
end
|
286
|
+
|
287
|
+
def weighted_total skip_cache = false, save_scope = nil
|
288
|
+
if !skip_cache && self.respond_to?(scope_cache_field :cached_weighted_total, save_scope)
|
289
|
+
return self.send(scope_cache_field :cached_weighted_total, save_scope)
|
290
|
+
end
|
291
|
+
ups = get_up_saves(:save_scope => save_scope).sum(:save_weight)
|
292
|
+
downs = get_down_saves(:save_scope => save_scope).sum(:save_weight)
|
293
|
+
ups + downs
|
294
|
+
end
|
295
|
+
|
296
|
+
def weighted_score skip_cache = false, save_scope = nil
|
297
|
+
if !skip_cache && self.respond_to?(scope_cache_field :cached_weighted_score, save_scope)
|
298
|
+
return self.send(scope_cache_field :cached_weighted_score, save_scope)
|
299
|
+
end
|
300
|
+
ups = get_up_saves(:save_scope => save_scope).sum(:save_weight)
|
301
|
+
downs = get_down_saves(:save_scope => save_scope).sum(:save_weight)
|
302
|
+
ups - downs
|
303
|
+
end
|
304
|
+
|
305
|
+
def weighted_average skip_cache = false, save_scope = nil
|
306
|
+
if !skip_cache && self.respond_to?(scope_cache_field :cached_weighted_average, save_scope)
|
307
|
+
return self.send(scope_cache_field :cached_weighted_average, save_scope)
|
308
|
+
end
|
309
|
+
|
310
|
+
count = count_saves_total(skip_cache, save_scope).to_i
|
311
|
+
if count > 0
|
312
|
+
weighted_score(skip_cache, save_scope).to_f / count
|
313
|
+
else
|
314
|
+
0.0
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
# savers
|
319
|
+
def saved_on_by? saver
|
320
|
+
saves = find_saves_for :saver_id => saver.id, :saver_type => saver.class.base_class.name
|
321
|
+
saves.count > 0
|
322
|
+
end
|
323
|
+
|
324
|
+
private
|
325
|
+
|
326
|
+
def scope_or_empty_hash(save_scope)
|
327
|
+
save_scope ? { :save_scope => save_scope } : {}
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|