ee_preferences 0.4.3 → 0.6.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 +8 -8
- data/.gitignore +0 -3
- data/CHANGELOG.rdoc +5 -1
- data/README.rdoc +2 -10
- data/Rakefile +1 -36
- data/{generators/preferences → lib/generators}/USAGE +1 -1
- data/lib/generators/preferences_generator.rb +17 -0
- data/{generators/preferences/templates/001_create_preferences.rb → lib/generators/templates/create_preferences.rb} +1 -5
- data/lib/preferences/engine.rb +4 -0
- data/lib/preferences/version.rb +1 -1
- data/lib/preferences.rb +134 -128
- data/preferences.gemspec +20 -17
- metadata +23 -30
- data/.travis.yml +0 -3
- data/Gemfile +0 -3
- data/generators/preferences/preferences_generator.rb +0 -7
- data/init.rb +0 -1
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZGE4N2ZiN2RhZGNiNzUyNWY5Nzk4YzMxNzQ3OGJjZmMyOTgyNDBmYg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MmNlMjY5ZGFkOGRjOWYxYmZiNWQ0ZGMzY2EyZWU2ZDNlNzU1NTgwYg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZTJkMmEyNzUxOGU1YTlkMjUwMDkxMDJhOTE0NGIxZjEwMmI5N2RmNTJhYjk1
|
10
|
+
MjM0MDJiOGM5YTNjY2JhNDZkZTZjYzk1ZmY4MTY3ZjIwODM1NzU5ZTY2ZDA3
|
11
|
+
YmVhNGZkN2Y2ZDExNmJiMGI1NGYzZTE2NmU1NzMxYzhkNTU3YzU=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NzM3NzIzNWFhY2M3YjdiZWIwNTIxZGRhNGFlYzE0NGRmNTcxYzEyZTNkZTY0
|
14
|
+
ZWJlMzJiMGRiYWUxNTNiMmUwYTg3ZjhlMzBiMjNmYWRkNWY3MjY3NjhhZTU1
|
15
|
+
MTJkNzVkOGJjNmM4ODE2NjZiNzc0YjM5MGJkOWFjYzFhYTBiYzg=
|
data/.gitignore
CHANGED
data/CHANGELOG.rdoc
CHANGED
data/README.rdoc
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
== preferences
|
1
|
+
== preferences
|
2
2
|
|
3
3
|
+preferences+ adds support for easily creating custom preferences for models.
|
4
4
|
|
@@ -10,24 +10,16 @@ API
|
|
10
10
|
|
11
11
|
Bugs
|
12
12
|
|
13
|
-
* http://
|
13
|
+
* http://pluginaweek.lighthouseapp.com/projects/13286-preferences
|
14
14
|
|
15
15
|
Development
|
16
16
|
|
17
17
|
* http://github.com/pluginaweek/preferences
|
18
18
|
|
19
|
-
Testing
|
20
|
-
|
21
|
-
* http://travis-ci.org/pluginaweek/preferences
|
22
|
-
|
23
19
|
Source
|
24
20
|
|
25
21
|
* git://github.com/pluginaweek/preferences.git
|
26
22
|
|
27
|
-
Mailing List
|
28
|
-
|
29
|
-
* http://groups.google.com/group/pluginaweek-talk
|
30
|
-
|
31
23
|
== Description
|
32
24
|
|
33
25
|
Preferences for models within an application, such as for users, is a pretty
|
data/Rakefile
CHANGED
@@ -1,36 +1 @@
|
|
1
|
-
require
|
2
|
-
require 'rake'
|
3
|
-
require 'rake/testtask'
|
4
|
-
require 'rake/rdoctask'
|
5
|
-
|
6
|
-
desc 'Default: run all tests.'
|
7
|
-
task :default => :test
|
8
|
-
|
9
|
-
desc "Test preferences."
|
10
|
-
Rake::TestTask.new(:test) do |t|
|
11
|
-
t.libs << 'lib'
|
12
|
-
t.test_files = Dir['test/**/*_test.rb']
|
13
|
-
t.verbose = true
|
14
|
-
end
|
15
|
-
|
16
|
-
begin
|
17
|
-
require 'rcov/rcovtask'
|
18
|
-
namespace :test do
|
19
|
-
desc "Test preferences with Rcov."
|
20
|
-
Rcov::RcovTask.new(:rcov) do |t|
|
21
|
-
t.libs << 'lib'
|
22
|
-
t.test_files = Dir['test/**/*_test.rb']
|
23
|
-
t.rcov_opts << '--exclude="^(?!lib/|app/)"'
|
24
|
-
t.verbose = true
|
25
|
-
end
|
26
|
-
end
|
27
|
-
rescue LoadError
|
28
|
-
end
|
29
|
-
|
30
|
-
desc "Generate documentation for preferences."
|
31
|
-
Rake::RDocTask.new(:rdoc) do |rdoc|
|
32
|
-
rdoc.rdoc_dir = 'rdoc'
|
33
|
-
rdoc.title = 'preferences'
|
34
|
-
rdoc.options << '--line-numbers' << '--inline-source' << '--main=README.rdoc'
|
35
|
-
rdoc.rdoc_files.include('README.rdoc', 'CHANGELOG.rdoc', 'LICENSE', 'lib/**/*.rb', 'app/**/*.rb')
|
36
|
-
end
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class PreferencesGenerator < Rails::Generators::Base
|
2
|
+
include Rails::Generators::Migration
|
3
|
+
|
4
|
+
source_root File.expand_path("../templates", __FILE__)
|
5
|
+
|
6
|
+
def self.next_migration_number(dirname)
|
7
|
+
if ActiveRecord::Base.timestamped_migrations
|
8
|
+
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
9
|
+
else
|
10
|
+
"%.3d" % (current_migration_number(dirname) + 1)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def create_migration_file
|
15
|
+
migration_template 'create_preferences.rb', "db/migrate/create_preferences.rb"
|
16
|
+
end
|
17
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class CreatePreferences < ActiveRecord::Migration
|
2
|
-
def
|
2
|
+
def change
|
3
3
|
create_table :preferences do |t|
|
4
4
|
t.string :name, :null => false
|
5
5
|
t.references :owner, :polymorphic => true, :null => false
|
@@ -9,8 +9,4 @@ class CreatePreferences < ActiveRecord::Migration
|
|
9
9
|
end
|
10
10
|
add_index :preferences, [:owner_id, :owner_type, :name, :group_id, :group_type], :unique => true, :name => 'index_preferences_on_owner_and_name_and_preference'
|
11
11
|
end
|
12
|
-
|
13
|
-
def self.down
|
14
|
-
drop_table :preferences
|
15
|
-
end
|
16
12
|
end
|
data/lib/preferences/version.rb
CHANGED
data/lib/preferences.rb
CHANGED
@@ -1,46 +1,47 @@
|
|
1
|
+
require 'preferences/engine'
|
1
2
|
require 'preferences/preference_definition'
|
2
3
|
|
3
4
|
# Adds support for defining preferences on ActiveRecord models.
|
4
|
-
#
|
5
|
+
#
|
5
6
|
# == Saving preferences
|
6
|
-
#
|
7
|
+
#
|
7
8
|
# Preferences are not automatically saved when they are set. You must save
|
8
9
|
# the record that the preferences were set on.
|
9
|
-
#
|
10
|
+
#
|
10
11
|
# For example,
|
11
|
-
#
|
12
|
+
#
|
12
13
|
# class User < ActiveRecord::Base
|
13
14
|
# preference :notifications
|
14
15
|
# end
|
15
|
-
#
|
16
|
+
#
|
16
17
|
# u = User.new(:login => 'admin', :prefers_notifications => false)
|
17
18
|
# u.save!
|
18
|
-
#
|
19
|
+
#
|
19
20
|
# u = User.find_by_login('admin')
|
20
21
|
# u.attributes = {:prefers_notifications => true}
|
21
22
|
# u.save!
|
22
|
-
#
|
23
|
+
#
|
23
24
|
# == Validations
|
24
|
-
#
|
25
|
+
#
|
25
26
|
# Since the generated accessors for a preference allow the preference to be
|
26
27
|
# treated just like regular ActiveRecord attributes, they can also be
|
27
28
|
# validated against in the same way. For example,
|
28
|
-
#
|
29
|
+
#
|
29
30
|
# class User < ActiveRecord::Base
|
30
31
|
# preference :color, :string
|
31
|
-
#
|
32
|
+
#
|
32
33
|
# validates_presence_of :preferred_color
|
33
34
|
# validates_inclusion_of :preferred_color, :in => %w(red green blue)
|
34
35
|
# end
|
35
|
-
#
|
36
|
+
#
|
36
37
|
# u = User.new
|
37
38
|
# u.valid? # => false
|
38
39
|
# u.errors.on(:preferred_color) # => "can't be blank"
|
39
|
-
#
|
40
|
+
#
|
40
41
|
# u.preferred_color = 'white'
|
41
42
|
# u.valid? # => false
|
42
43
|
# u.errors.on(:preferred_color) # => "is not included in the list"
|
43
|
-
#
|
44
|
+
#
|
44
45
|
# u.preferred_color = 'red'
|
45
46
|
# u.valid? # => true
|
46
47
|
module Preferences
|
@@ -48,66 +49,66 @@ module Preferences
|
|
48
49
|
# Defines a new preference for all records in the model. By default,
|
49
50
|
# preferences are assumed to have a boolean data type, so all values will
|
50
51
|
# be typecasted to true/false based on ActiveRecord rules.
|
51
|
-
#
|
52
|
+
#
|
52
53
|
# Configuration options:
|
53
54
|
# * <tt>:default</tt> - The default value for the preference. Default is nil.
|
54
55
|
# * <tt>:group_defaults</tt> - Defines the default values to use for various
|
55
56
|
# groups. This should map group_name -> defaults. For ActiveRecord groups,
|
56
|
-
# use the class name.
|
57
|
-
#
|
57
|
+
# use the class name.
|
58
|
+
#
|
58
59
|
# == Examples
|
59
|
-
#
|
60
|
+
#
|
60
61
|
# The example below shows the various ways to define a preference for a
|
61
62
|
# particular model.
|
62
|
-
#
|
63
|
+
#
|
63
64
|
# class User < ActiveRecord::Base
|
64
65
|
# preference :notifications, :default => false
|
65
66
|
# preference :color, :string, :default => 'red', :group_defaults => {:car => 'black'}
|
66
67
|
# preference :favorite_number, :integer
|
67
68
|
# preference :data, :any # Allows any data type to be stored
|
68
69
|
# end
|
69
|
-
#
|
70
|
+
#
|
70
71
|
# All preferences are also inherited by subclasses.
|
71
|
-
#
|
72
|
+
#
|
72
73
|
# == Associations
|
73
|
-
#
|
74
|
+
#
|
74
75
|
# After the first preference is defined, the following associations are
|
75
76
|
# created for the model:
|
76
77
|
# * +stored_preferences+ - A collection of all the custom preferences
|
77
78
|
# specified for a record. This will not include default preferences
|
78
79
|
# unless they have been explicitly set.
|
79
|
-
#
|
80
|
+
#
|
80
81
|
# == Named scopes
|
81
|
-
#
|
82
|
+
#
|
82
83
|
# In addition to the above associations, the following named scopes get
|
83
84
|
# generated for the model:
|
84
85
|
# * +with_preferences+ - Finds all records with a given set of preferences
|
85
86
|
# * +without_preferences+ - Finds all records without a given set of preferences
|
86
|
-
#
|
87
|
+
#
|
87
88
|
# In addition to utilizing preferences stored in the database, each of the
|
88
89
|
# above scopes also take into account the defaults that have been defined
|
89
90
|
# for each preference.
|
90
|
-
#
|
91
|
+
#
|
91
92
|
# Example:
|
92
|
-
#
|
93
|
+
#
|
93
94
|
# User.with_preferences(:notifications => true)
|
94
95
|
# User.with_preferences(:notifications => true, :color => 'blue')
|
95
|
-
#
|
96
|
+
#
|
96
97
|
# # Searching with group preferences
|
97
98
|
# car = Car.find(:first)
|
98
99
|
# User.with_preferences(car => {:color => 'blue'})
|
99
100
|
# User.with_preferences(:notifications => true, car => {:color => 'blue'})
|
100
|
-
#
|
101
|
+
#
|
101
102
|
# == Generated accessors
|
102
|
-
#
|
103
|
+
#
|
103
104
|
# In addition to calling <tt>prefers?</tt> and +preferred+ on a record,
|
104
105
|
# you can also use the shortcut accessor methods that are generated when a
|
105
106
|
# preference is defined. For example,
|
106
|
-
#
|
107
|
+
#
|
107
108
|
# class User < ActiveRecord::Base
|
108
109
|
# preference :notifications
|
109
110
|
# end
|
110
|
-
#
|
111
|
+
#
|
111
112
|
# ...generates the following methods:
|
112
113
|
# * <tt>prefers_notifications?</tt> - Whether a value has been specified, i.e. <tt>record.prefers?(:notifications)</tt>
|
113
114
|
# * <tt>prefers_notifications</tt> - The actual value stored, i.e. <tt>record.prefers(:notifications)</tt>
|
@@ -117,7 +118,7 @@ module Preferences
|
|
117
118
|
# * <tt>prefers_notifications_change</tt> - A list of [original_value, new_value] if the preference has changed
|
118
119
|
# * <tt>prefers_notifications_will_change!</tt> - Forces the preference to get updated
|
119
120
|
# * <tt>reset_prefers_notifications!</tt> - Reverts any unsaved changes to the preference
|
120
|
-
#
|
121
|
+
#
|
121
122
|
# ...and the equivalent +preferred+ methods:
|
122
123
|
# * <tt>preferred_notifications?</tt>
|
123
124
|
# * <tt>preferred_notifications</tt>
|
@@ -127,108 +128,108 @@ module Preferences
|
|
127
128
|
# * <tt>preferred_notifications_change</tt>
|
128
129
|
# * <tt>preferred_notifications_will_change!</tt>
|
129
130
|
# * <tt>reset_preferred_notifications!</tt>
|
130
|
-
#
|
131
|
+
#
|
131
132
|
# Notice that there are two tenses used depending on the context of the
|
132
133
|
# preference. Conventionally, <tt>prefers_notifications?</tt> is better
|
133
134
|
# for accessing boolean preferences, while +preferred_color+ is better for
|
134
135
|
# accessing non-boolean preferences.
|
135
|
-
#
|
136
|
+
#
|
136
137
|
# Example:
|
137
|
-
#
|
138
|
+
#
|
138
139
|
# user = User.find(:first)
|
139
140
|
# user.prefers_notifications? # => false
|
140
141
|
# user.prefers_notifications # => false
|
141
142
|
# user.preferred_color? # => true
|
142
143
|
# user.preferred_color # => 'red'
|
143
144
|
# user.preferred_color = 'blue' # => 'blue'
|
144
|
-
#
|
145
|
+
#
|
145
146
|
# user.prefers_notifications = true
|
146
|
-
#
|
147
|
+
#
|
147
148
|
# car = Car.find(:first)
|
148
149
|
# user.preferred_color = 'red', car # => 'red'
|
149
150
|
# user.preferred_color(car) # => 'red'
|
150
151
|
# user.preferred_color?(car) # => true
|
151
|
-
#
|
152
|
+
#
|
152
153
|
# user.save! # => true
|
153
154
|
def preference(name, *args)
|
154
155
|
unless included_modules.include?(InstanceMethods)
|
155
|
-
|
156
|
+
class_attribute :preference_definitions
|
156
157
|
self.preference_definitions = {}
|
157
|
-
|
158
|
+
|
158
159
|
has_many :stored_preferences, :as => :owner, :class_name => 'Preference'
|
159
|
-
|
160
|
+
|
160
161
|
after_save :update_preferences
|
161
162
|
before_destroy :destroy_preferences
|
162
163
|
|
163
164
|
# Named scopes
|
164
165
|
scope :with_preferences, lambda {|preferences| build_preference_scope(preferences)}
|
165
166
|
scope :without_preferences, lambda {|preferences| build_preference_scope(preferences, true)}
|
166
|
-
|
167
|
+
|
167
168
|
extend Preferences::ClassMethods
|
168
169
|
include Preferences::InstanceMethods
|
169
170
|
end
|
170
|
-
|
171
|
+
|
171
172
|
# Create the definition
|
172
173
|
name = name.to_s
|
173
174
|
definition = PreferenceDefinition.new(name, *args)
|
174
175
|
self.preference_definitions[name] = definition
|
175
|
-
|
176
|
+
|
176
177
|
# Create short-hand accessor methods, making sure that the name
|
177
178
|
# is method-safe in terms of what characters are allowed
|
178
179
|
name = name.gsub(/[^A-Za-z0-9_-]/, '').underscore
|
179
|
-
|
180
|
+
|
180
181
|
# Query lookup
|
181
182
|
define_method("preferred_#{name}?") do |*group|
|
182
183
|
preferred?(name, group.first)
|
183
184
|
end
|
184
185
|
alias_method "prefers_#{name}?", "preferred_#{name}?"
|
185
|
-
|
186
|
+
|
186
187
|
# Reader
|
187
188
|
define_method("preferred_#{name}") do |*group|
|
188
189
|
preferred(name, group.first)
|
189
190
|
end
|
190
191
|
alias_method "prefers_#{name}", "preferred_#{name}"
|
191
|
-
|
192
|
+
|
192
193
|
# Writer
|
193
194
|
define_method("preferred_#{name}=") do |*args|
|
194
195
|
write_preference(*args.flatten.unshift(name))
|
195
196
|
end
|
196
197
|
alias_method "prefers_#{name}=", "preferred_#{name}="
|
197
|
-
|
198
|
+
|
198
199
|
# Changes
|
199
200
|
define_method("preferred_#{name}_changed?") do |*group|
|
200
201
|
preference_changed?(name, group.first)
|
201
202
|
end
|
202
203
|
alias_method "prefers_#{name}_changed?", "preferred_#{name}_changed?"
|
203
|
-
|
204
|
+
|
204
205
|
define_method("preferred_#{name}_was") do |*group|
|
205
206
|
preference_was(name, group.first)
|
206
207
|
end
|
207
208
|
alias_method "prefers_#{name}_was", "preferred_#{name}_was"
|
208
|
-
|
209
|
+
|
209
210
|
define_method("preferred_#{name}_change") do |*group|
|
210
211
|
preference_change(name, group.first)
|
211
212
|
end
|
212
213
|
alias_method "prefers_#{name}_change", "preferred_#{name}_change"
|
213
|
-
|
214
|
+
|
214
215
|
define_method("preferred_#{name}_will_change!") do |*group|
|
215
216
|
preference_will_change!(name, group.first)
|
216
217
|
end
|
217
218
|
alias_method "prefers_#{name}_will_change!", "preferred_#{name}_will_change!"
|
218
|
-
|
219
|
+
|
219
220
|
define_method("reset_preferred_#{name}!") do |*group|
|
220
221
|
reset_preference!(name, group.first)
|
221
222
|
end
|
222
223
|
alias_method "reset_prefers_#{name}!", "reset_preferred_#{name}!"
|
223
|
-
|
224
|
+
|
224
225
|
definition
|
225
226
|
end
|
226
227
|
end
|
227
|
-
|
228
|
+
|
228
229
|
module ClassMethods #:nodoc:
|
229
230
|
# Generates the scope for looking under records with a specific set of
|
230
231
|
# preferences associated with them.
|
231
|
-
#
|
232
|
+
#
|
232
233
|
# Note thate this is a bit more complicated than usual since the preference
|
233
234
|
# definitions aren't in the database for joins, defaults need to be accounted
|
234
235
|
# for, and querying for the the presence of multiple preferences requires
|
@@ -237,7 +238,7 @@ module Preferences
|
|
237
238
|
joins = []
|
238
239
|
statements = []
|
239
240
|
values = []
|
240
|
-
|
241
|
+
|
241
242
|
# Flatten the preferences for easier processing
|
242
243
|
preferences = preferences.inject({}) do |result, (group, value)|
|
243
244
|
if value.is_a?(Hash)
|
@@ -247,16 +248,16 @@ module Preferences
|
|
247
248
|
end
|
248
249
|
result
|
249
250
|
end
|
250
|
-
|
251
|
+
|
251
252
|
preferences.each do |(group, preference), value|
|
252
253
|
group_id, group_type = Preference.split_group(group)
|
253
254
|
preference = preference.to_s
|
254
255
|
definition = preference_definitions[preference.to_s]
|
255
256
|
value = definition.type_cast(value)
|
256
257
|
is_default = definition.default_value(group_type) == value
|
257
|
-
|
258
|
+
|
258
259
|
table = "preferences_#{group_id}_#{group_type}_#{preference}"
|
259
|
-
|
260
|
+
|
260
261
|
# Since each preference is a different record, they need their own
|
261
262
|
# join so that the proper conditions can be set
|
262
263
|
joins << "LEFT JOIN preferences AS #{table} ON #{table}.owner_id = #{table_name}.#{primary_key} AND " + sanitize_sql(
|
@@ -265,7 +266,7 @@ module Preferences
|
|
265
266
|
"#{table}.group_type" => group_type,
|
266
267
|
"#{table}.name" => preference
|
267
268
|
)
|
268
|
-
|
269
|
+
|
269
270
|
if inverse
|
270
271
|
statements << "#{table}.id IS NOT NULL AND #{table}.value " + (value.nil? ? ' IS NOT NULL' : ' != ?') + (!is_default ? " OR #{table}.id IS NULL" : '')
|
271
272
|
else
|
@@ -273,104 +274,104 @@ module Preferences
|
|
273
274
|
end
|
274
275
|
values << value unless value.nil?
|
275
276
|
end
|
276
|
-
|
277
|
+
|
277
278
|
sql = statements.map! {|statement| "(#{statement})"} * ' AND '
|
278
279
|
{:joins => joins, :conditions => values.unshift(sql)}
|
279
280
|
end
|
280
281
|
end
|
281
|
-
|
282
|
+
|
282
283
|
module InstanceMethods
|
283
284
|
def self.included(base) #:nodoc:
|
284
285
|
base.class_eval do
|
285
286
|
alias_method :prefs, :preferences
|
286
287
|
end
|
287
288
|
end
|
288
|
-
|
289
|
+
|
289
290
|
# Finds all preferences, including defaults, for the current record. If
|
290
291
|
# looking up custom group preferences, then this will include all default
|
291
292
|
# preferences within that particular group as well.
|
292
|
-
#
|
293
|
+
#
|
293
294
|
# == Examples
|
294
|
-
#
|
295
|
+
#
|
295
296
|
# A user with no stored values:
|
296
|
-
#
|
297
|
+
#
|
297
298
|
# user = User.find(:first)
|
298
299
|
# user.preferences
|
299
300
|
# => {"language"=>"English", "color"=>nil}
|
300
|
-
#
|
301
|
+
#
|
301
302
|
# A user with stored values for a particular group:
|
302
|
-
#
|
303
|
+
#
|
303
304
|
# user.preferred_color = 'red', :cars
|
304
305
|
# user.preferences(:cars)
|
305
306
|
# => {"language=>"English", "color"=>"red"}
|
306
307
|
def preferences(group = nil)
|
307
308
|
preferences = preferences_group(group)
|
308
|
-
|
309
|
+
|
309
310
|
unless preferences_group_loaded?(group)
|
310
311
|
group_id, group_type = Preference.split_group(group)
|
311
312
|
find_preferences(:group_id => group_id, :group_type => group_type).each do |preference|
|
312
313
|
preferences[preference.name] = preference.value unless preferences.include?(preference.name)
|
313
314
|
end
|
314
|
-
|
315
|
+
|
315
316
|
# Add defaults
|
316
317
|
preference_definitions.each do |name, definition|
|
317
318
|
preferences[name] = definition.default_value(group_type) unless preferences.include?(name)
|
318
319
|
end
|
319
320
|
end
|
320
|
-
|
321
|
+
|
321
322
|
preferences.inject({}) do |typed_preferences, (name, value)|
|
322
323
|
typed_preferences[name] = value.nil? ? value : preference_definitions[name].type_cast(value)
|
323
324
|
typed_preferences
|
324
325
|
end
|
325
326
|
end
|
326
|
-
|
327
|
+
|
327
328
|
# Queries whether or not a value is present for the given preference.
|
328
329
|
# This is dependent on how the value is type-casted.
|
329
|
-
#
|
330
|
+
#
|
330
331
|
# == Examples
|
331
|
-
#
|
332
|
+
#
|
332
333
|
# class User < ActiveRecord::Base
|
333
334
|
# preference :color, :string, :default => 'red'
|
334
335
|
# end
|
335
|
-
#
|
336
|
+
#
|
336
337
|
# user = User.create
|
337
338
|
# user.preferred(:color) # => "red"
|
338
339
|
# user.preferred?(:color) # => true
|
339
340
|
# user.preferred?(:color, 'cars') # => true
|
340
341
|
# user.preferred?(:color, Car.first) # => true
|
341
|
-
#
|
342
|
+
#
|
342
343
|
# user.write_preference(:color, nil)
|
343
344
|
# user.preferred(:color) # => nil
|
344
345
|
# user.preferred?(:color) # => false
|
345
346
|
def preferred?(name, group = nil)
|
346
347
|
name = name.to_s
|
347
348
|
assert_valid_preference(name)
|
348
|
-
|
349
|
+
|
349
350
|
value = preferred(name, group)
|
350
351
|
preference_definitions[name].query(value)
|
351
352
|
end
|
352
353
|
alias_method :prefers?, :preferred?
|
353
|
-
|
354
|
+
|
354
355
|
# Gets the actual value stored for the given preference, or the default
|
355
356
|
# value if nothing is present.
|
356
|
-
#
|
357
|
+
#
|
357
358
|
# == Examples
|
358
|
-
#
|
359
|
+
#
|
359
360
|
# class User < ActiveRecord::Base
|
360
361
|
# preference :color, :string, :default => 'red'
|
361
362
|
# end
|
362
|
-
#
|
363
|
+
#
|
363
364
|
# user = User.create
|
364
365
|
# user.preferred(:color) # => "red"
|
365
366
|
# user.preferred(:color, 'cars') # => "red"
|
366
367
|
# user.preferred(:color, Car.first) # => "red"
|
367
|
-
#
|
368
|
+
#
|
368
369
|
# user.write_preference(:color, 'blue')
|
369
370
|
# user.preferred(:color) # => "blue"
|
370
371
|
def preferred(name, group = nil)
|
371
372
|
name = name.to_s
|
372
373
|
assert_valid_preference(name)
|
373
|
-
|
374
|
+
|
374
375
|
if preferences_group(group).include?(name)
|
375
376
|
# Value for this group/name has been written, but not saved yet:
|
376
377
|
# grab from the pending values
|
@@ -379,35 +380,35 @@ module Preferences
|
|
379
380
|
# Grab the first preference; if it doesn't exist, use the default value
|
380
381
|
group_id, group_type = Preference.split_group(group)
|
381
382
|
preference = find_preferences(:name => name, :group_id => group_id, :group_type => group_type).first unless preferences_group_loaded?(group)
|
382
|
-
|
383
|
+
|
383
384
|
value = preference ? preference.value : preference_definitions[name].default_value(group_type)
|
384
385
|
preferences_group(group)[name] = value
|
385
386
|
end
|
386
|
-
|
387
|
+
|
387
388
|
definition = preference_definitions[name]
|
388
389
|
value = definition.type_cast(value) unless value.nil?
|
389
390
|
value
|
390
391
|
end
|
391
392
|
alias_method :prefers, :preferred
|
392
|
-
|
393
|
+
|
393
394
|
# Sets a new value for the given preference. The actual Preference record
|
394
395
|
# is *not* created until this record is saved. In this way, preferences
|
395
396
|
# act *exactly* the same as attributes. They can be written to and
|
396
397
|
# validated against, but won't actually be written to the database until
|
397
398
|
# the record is saved.
|
398
|
-
#
|
399
|
+
#
|
399
400
|
# == Examples
|
400
|
-
#
|
401
|
+
#
|
401
402
|
# user = User.find(:first)
|
402
403
|
# user.write_preference(:color, 'red') # => "red"
|
403
404
|
# user.save!
|
404
|
-
#
|
405
|
+
#
|
405
406
|
# user.write_preference(:color, 'blue', Car.first) # => "blue"
|
406
407
|
# user.save!
|
407
408
|
def write_preference(name, value, group = nil)
|
408
409
|
name = name.to_s
|
409
410
|
assert_valid_preference(name)
|
410
|
-
|
411
|
+
|
411
412
|
preferences_changed = preferences_changed_group(group)
|
412
413
|
if preferences_changed.include?(name)
|
413
414
|
old = preferences_changed[name]
|
@@ -416,24 +417,24 @@ module Preferences
|
|
416
417
|
old = clone_preference_value(name, group)
|
417
418
|
preferences_changed[name] = old if preference_value_changed?(name, old, value)
|
418
419
|
end
|
419
|
-
|
420
|
-
value =
|
420
|
+
|
421
|
+
value = ActiveRecord::ConnectionAdapters::Column.value_to_integer(value) if preference_definitions[name].number?
|
421
422
|
preferences_group(group)[name] = value
|
422
|
-
|
423
|
+
|
423
424
|
value
|
424
425
|
end
|
425
|
-
|
426
|
+
|
426
427
|
# Whether any attributes have unsaved changes.
|
427
|
-
#
|
428
|
+
#
|
428
429
|
# == Examples
|
429
|
-
#
|
430
|
+
#
|
430
431
|
# user = User.find(:first)
|
431
432
|
# user.preferences_changed? # => false
|
432
433
|
# user.write_preference(:color, 'red')
|
433
434
|
# user.preferences_changed? # => true
|
434
435
|
# user.save
|
435
436
|
# user.preferences_changed? # => false
|
436
|
-
#
|
437
|
+
#
|
437
438
|
# # Groups
|
438
439
|
# user.preferences_changed?(:car) # => false
|
439
440
|
# user.write_preference(:color, 'red', :car)
|
@@ -441,18 +442,18 @@ module Preferences
|
|
441
442
|
def preferences_changed?(group = nil)
|
442
443
|
!preferences_changed_group(group).empty?
|
443
444
|
end
|
444
|
-
|
445
|
+
|
445
446
|
# A list of the preferences that have unsaved changes.
|
446
|
-
#
|
447
|
+
#
|
447
448
|
# == Examples
|
448
|
-
#
|
449
|
+
#
|
449
450
|
# user = User.find(:first)
|
450
451
|
# user.preferences_changed # => []
|
451
452
|
# user.write_preference(:color, 'red')
|
452
453
|
# user.preferences_changed # => ["color"]
|
453
454
|
# user.save
|
454
455
|
# user.preferences_changed # => []
|
455
|
-
#
|
456
|
+
#
|
456
457
|
# # Groups
|
457
458
|
# user.preferences_changed(:car) # => []
|
458
459
|
# user.write_preference(:color, 'red', :car)
|
@@ -460,20 +461,20 @@ module Preferences
|
|
460
461
|
def preferences_changed(group = nil)
|
461
462
|
preferences_changed_group(group).keys
|
462
463
|
end
|
463
|
-
|
464
|
+
|
464
465
|
# A map of the preferences that have changed in the current object.
|
465
|
-
#
|
466
|
+
#
|
466
467
|
# == Examples
|
467
|
-
#
|
468
|
+
#
|
468
469
|
# user = User.find(:first)
|
469
470
|
# user.preferred(:color) # => nil
|
470
471
|
# user.preference_changes # => {}
|
471
|
-
#
|
472
|
+
#
|
472
473
|
# user.write_preference(:color, 'red')
|
473
474
|
# user.preference_changes # => {"color" => [nil, "red"]}
|
474
475
|
# user.save
|
475
476
|
# user.preference_changes # => {}
|
476
|
-
#
|
477
|
+
#
|
477
478
|
# # Groups
|
478
479
|
# user.preferred(:color, :car) # => nil
|
479
480
|
# user.preference_changes(:car) # => {}
|
@@ -485,36 +486,36 @@ module Preferences
|
|
485
486
|
changes
|
486
487
|
end
|
487
488
|
end
|
488
|
-
|
489
|
+
|
489
490
|
# Reloads the pereferences of this object as well as its attributes
|
490
491
|
def reload(*args) #:nodoc:
|
491
492
|
result = super
|
492
|
-
|
493
|
+
|
493
494
|
@preferences.clear if @preferences
|
494
495
|
@preferences_changed.clear if @preferences_changed
|
495
|
-
|
496
|
+
|
496
497
|
result
|
497
498
|
end
|
498
|
-
|
499
|
+
|
499
500
|
private
|
500
501
|
# Asserts that the given name is a valid preference in this model. If it
|
501
502
|
# is not, then an ArgumentError exception is raised.
|
502
503
|
def assert_valid_preference(name)
|
503
504
|
raise(ArgumentError, "Unknown preference: #{name}") unless preference_definitions.include?(name)
|
504
505
|
end
|
505
|
-
|
506
|
+
|
506
507
|
# Gets the set of preferences identified by the given group
|
507
508
|
def preferences_group(group)
|
508
509
|
@preferences ||= {}
|
509
510
|
@preferences[group.is_a?(Symbol) ? group.to_s : group] ||= {}
|
510
511
|
end
|
511
|
-
|
512
|
+
|
512
513
|
# Determines whether the given group of preferences has already been
|
513
514
|
# loaded from the database
|
514
515
|
def preferences_group_loaded?(group)
|
515
516
|
preference_definitions.length == preferences_group(group).length
|
516
517
|
end
|
517
|
-
|
518
|
+
|
518
519
|
# Generates a clone of the current value stored for the preference with
|
519
520
|
# the given name / group
|
520
521
|
def clone_preference_value(name, group)
|
@@ -523,41 +524,41 @@ module Preferences
|
|
523
524
|
rescue TypeError, NoMethodError
|
524
525
|
value
|
525
526
|
end
|
526
|
-
|
527
|
+
|
527
528
|
# Keeps track of all preferences that have been changed so that they can
|
528
529
|
# be properly updated in the database. Maps group -> preference -> value.
|
529
530
|
def preferences_changed_group(group)
|
530
531
|
@preferences_changed ||= {}
|
531
532
|
@preferences_changed[group.is_a?(Symbol) ? group.to_s : group] ||= {}
|
532
533
|
end
|
533
|
-
|
534
|
+
|
534
535
|
# Determines whether a preference changed in the given group
|
535
536
|
def preference_changed?(name, group)
|
536
537
|
preferences_changed_group(group).include?(name)
|
537
538
|
end
|
538
|
-
|
539
|
+
|
539
540
|
# Builds an array of [original_value, new_value] for the given preference.
|
540
541
|
# If the perference did not change, this will return nil.
|
541
542
|
def preference_change(name, group)
|
542
543
|
[preferences_changed_group(group)[name], preferred(name, group)] if preference_changed?(name, group)
|
543
544
|
end
|
544
|
-
|
545
|
+
|
545
546
|
# Gets the last saved value for the given preference
|
546
547
|
def preference_was(name, group)
|
547
548
|
preference_changed?(name, group) ? preferences_changed_group(group)[name] : preferred(name, group)
|
548
549
|
end
|
549
|
-
|
550
|
+
|
550
551
|
# Forces the given preference to be saved regardless of whether the value
|
551
552
|
# is actually diferent
|
552
553
|
def preference_will_change!(name, group)
|
553
554
|
preferences_changed_group(group)[name] = clone_preference_value(name, group)
|
554
555
|
end
|
555
|
-
|
556
|
+
|
556
557
|
# Reverts any unsaved changes to the given preference
|
557
558
|
def reset_preference!(name, group)
|
558
559
|
write_preference(name, preferences_changed_group(group)[name], group) if preference_changed?(name, group)
|
559
560
|
end
|
560
|
-
|
561
|
+
|
561
562
|
# Determines whether the old value is different from the new value for the
|
562
563
|
# given preference. This will use the typecasted value to determine
|
563
564
|
# equality.
|
@@ -572,40 +573,45 @@ module Preferences
|
|
572
573
|
else
|
573
574
|
value = definition.type_cast(value)
|
574
575
|
end
|
575
|
-
|
576
|
+
|
576
577
|
old != value
|
577
578
|
end
|
578
|
-
|
579
|
+
|
579
580
|
# Updates any preferences that have been changed/added since the record
|
580
581
|
# was last saved
|
581
582
|
def update_preferences
|
582
583
|
if @preferences_changed
|
583
584
|
@preferences_changed.each do |group, preferences|
|
584
585
|
group_id, group_type = Preference.split_group(group)
|
585
|
-
|
586
|
+
|
586
587
|
preferences.keys.each do |name|
|
587
588
|
# Find an existing preference or build a new one
|
588
589
|
attributes = {:name => name, :group_id => group_id, :group_type => group_type}
|
589
|
-
|
590
|
+
|
591
|
+
unless (preference = find_preferences(attributes).first)
|
592
|
+
preference = stored_preferences.build
|
593
|
+
attributes.each_pair { |attribute, value| preference[attribute] = value }
|
594
|
+
end
|
595
|
+
|
590
596
|
preference.value = preferred(name, group)
|
591
597
|
preference.save!
|
592
598
|
end
|
593
599
|
end
|
594
|
-
|
600
|
+
|
595
601
|
@preferences_changed.clear
|
596
602
|
end
|
597
603
|
end
|
598
|
-
|
604
|
+
|
599
605
|
# Finds all stored preferences with the given attributes. This will do a
|
600
606
|
# smart lookup by looking at the in-memory collection if it was eager-
|
601
607
|
# loaded.
|
602
608
|
def find_preferences(attributes)
|
603
609
|
if stored_preferences.loaded?
|
604
610
|
stored_preferences.select do |preference|
|
605
|
-
attributes.all? {|attribute, value| preference[attribute] == value}
|
611
|
+
attributes.all? {|attribute, value| preference[attribute] == value}
|
606
612
|
end
|
607
613
|
else
|
608
|
-
stored_preferences.
|
614
|
+
stored_preferences.where(attributes)
|
609
615
|
end
|
610
616
|
end
|
611
617
|
end
|
data/preferences.gemspec
CHANGED
@@ -1,20 +1,23 @@
|
|
1
|
-
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
2
4
|
require 'preferences/version'
|
3
5
|
|
4
|
-
Gem::Specification.new do |
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ee_preferences"
|
8
|
+
spec.version = Preferences::VERSION
|
9
|
+
spec.authors = ["Aaron Pfeifer", "Jack Dempsey", "Brenda Strech"]
|
10
|
+
spec.email = ["aaron@pluginaweek.org"]
|
11
|
+
spec.description = %q{Adds support for easily creating custom preferences for ActiveRecord models. Fork for Rails 4.}
|
12
|
+
spec.summary = %q{Adds support for easily creating custom preferences for ActiveRecord models}
|
13
|
+
spec.homepage = %q{http://www.pluginaweek.org}
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
20
23
|
end
|
metadata
CHANGED
@@ -1,66 +1,64 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ee_preferences
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Pfeifer
|
8
|
+
- Jack Dempsey
|
9
|
+
- Brenda Strech
|
8
10
|
autorequire:
|
9
11
|
bindir: bin
|
10
12
|
cert_chain: []
|
11
13
|
date: 2014-09-08 00:00:00.000000000 Z
|
12
14
|
dependencies:
|
13
15
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
16
|
+
name: bundler
|
15
17
|
requirement: !ruby/object:Gem::Requirement
|
16
18
|
requirements:
|
17
|
-
- -
|
19
|
+
- - ~>
|
18
20
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
21
|
+
version: '1.3'
|
20
22
|
type: :development
|
21
23
|
prerelease: false
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
23
25
|
requirements:
|
24
|
-
- -
|
26
|
+
- - ~>
|
25
27
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
28
|
+
version: '1.3'
|
27
29
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
30
|
+
name: rake
|
29
31
|
requirement: !ruby/object:Gem::Requirement
|
30
32
|
requirements:
|
31
33
|
- - ! '>='
|
32
34
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0
|
35
|
+
version: '0'
|
34
36
|
type: :development
|
35
37
|
prerelease: false
|
36
38
|
version_requirements: !ruby/object:Gem::Requirement
|
37
39
|
requirements:
|
38
40
|
- - ! '>='
|
39
41
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0
|
42
|
+
version: '0'
|
41
43
|
description: Adds support for easily creating custom preferences for ActiveRecord
|
42
|
-
models
|
43
|
-
email:
|
44
|
+
models. Fork for Rails 4.
|
45
|
+
email:
|
46
|
+
- aaron@pluginaweek.org
|
44
47
|
executables: []
|
45
48
|
extensions: []
|
46
|
-
extra_rdoc_files:
|
47
|
-
- README.rdoc
|
48
|
-
- CHANGELOG.rdoc
|
49
|
-
- LICENSE
|
49
|
+
extra_rdoc_files: []
|
50
50
|
files:
|
51
51
|
- .gitignore
|
52
|
-
- .travis.yml
|
53
52
|
- CHANGELOG.rdoc
|
54
|
-
- Gemfile
|
55
53
|
- LICENSE
|
56
54
|
- README.rdoc
|
57
55
|
- Rakefile
|
58
56
|
- app/models/preference.rb
|
59
|
-
- generators/
|
60
|
-
- generators/
|
61
|
-
- generators/
|
62
|
-
- init.rb
|
57
|
+
- lib/generators/USAGE
|
58
|
+
- lib/generators/preferences_generator.rb
|
59
|
+
- lib/generators/templates/create_preferences.rb
|
63
60
|
- lib/preferences.rb
|
61
|
+
- lib/preferences/engine.rb
|
64
62
|
- lib/preferences/preference_definition.rb
|
65
63
|
- lib/preferences/version.rb
|
66
64
|
- preferences.gemspec
|
@@ -78,16 +76,11 @@ files:
|
|
78
76
|
- test/unit/preference_definition_test.rb
|
79
77
|
- test/unit/preference_test.rb
|
80
78
|
homepage: http://www.pluginaweek.org
|
81
|
-
licenses:
|
79
|
+
licenses:
|
80
|
+
- MIT
|
82
81
|
metadata: {}
|
83
82
|
post_install_message:
|
84
|
-
rdoc_options:
|
85
|
-
- --line-numbers
|
86
|
-
- --inline-source
|
87
|
-
- --title
|
88
|
-
- preferences
|
89
|
-
- --main
|
90
|
-
- README.rdoc
|
83
|
+
rdoc_options: []
|
91
84
|
require_paths:
|
92
85
|
- lib
|
93
86
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -105,7 +98,7 @@ rubyforge_project:
|
|
105
98
|
rubygems_version: 2.3.0
|
106
99
|
signing_key:
|
107
100
|
specification_version: 4
|
108
|
-
summary:
|
101
|
+
summary: Adds support for easily creating custom preferences for ActiveRecord models
|
109
102
|
test_files:
|
110
103
|
- test/app_root/app/models/car.rb
|
111
104
|
- test/app_root/app/models/employee.rb
|
data/.travis.yml
DELETED
data/Gemfile
DELETED
data/init.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'preferences'
|