acts-as-optionable 0.0.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +116 -0
- data/VERSION +1 -1
- data/lib/acts_as_optionable/acts_as_optionable.rb +39 -17
- data/lib/acts_as_optionable/specify_option.rb +12 -1
- data/spec/acts_as_optionable_spec.rb +22 -1
- data/spec/spec.opts +5 -0
- metadata +7 -6
- data/README +0 -13
data/README.rdoc
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
= ActsAsOptionable
|
2
|
+
|
3
|
+
*Warning* I don't recommend using this yet since I'm going to make a couple core changes shortly. Very alpha.
|
4
|
+
|
5
|
+
Support to add options, as well as specify default options, to ActiveRecord models. It's currently a very basic approach, and allows you to fetch options from an ActiveRecord model via an association, or via a hash or object where options are callable as methods. It doesn't support any advanced finder options.
|
6
|
+
|
7
|
+
It works by creating an options table which is polymorphic to ActiveRecord models which call acts_as_optionable.
|
8
|
+
|
9
|
+
The plugin also grants the ability to specify default options for a class, or pass in defaults to an instance at runtime.
|
10
|
+
|
11
|
+
== Installation
|
12
|
+
|
13
|
+
Available as a gem:
|
14
|
+
|
15
|
+
gem install acts-as-optionable
|
16
|
+
|
17
|
+
=== Post Installation
|
18
|
+
|
19
|
+
This creates an Option model in you app.
|
20
|
+
|
21
|
+
1. script/generate option
|
22
|
+
2. Rake db:migrate
|
23
|
+
|
24
|
+
== Usage
|
25
|
+
|
26
|
+
=== Adding options to a model
|
27
|
+
|
28
|
+
class Style < ActiveRecord::Base
|
29
|
+
acts_as_optionable
|
30
|
+
end
|
31
|
+
|
32
|
+
=== Setting, getting, and deleting options
|
33
|
+
|
34
|
+
Use #get_option, #set_option, and #delete_option for interacting with options.
|
35
|
+
|
36
|
+
style = Style.create
|
37
|
+
style.set_option("color", "red")
|
38
|
+
style.get_option("color").value => "red"
|
39
|
+
style.delete_option("color")
|
40
|
+
style.get_option("color") => nil
|
41
|
+
|
42
|
+
|
43
|
+
=== Specifying default options at the class level
|
44
|
+
|
45
|
+
class StyleWithDefaults < ActiveRecord::Base
|
46
|
+
acts_as_optionable
|
47
|
+
|
48
|
+
specify_option :background_color, :default => "white"
|
49
|
+
specify_option :color, :default => "black"
|
50
|
+
end
|
51
|
+
|
52
|
+
style = StyleWithDefaults.create
|
53
|
+
style.get_option("background_color").value => "white"
|
54
|
+
|
55
|
+
=== Specifying instance options at runtime
|
56
|
+
|
57
|
+
style.instance_specified_options = { :foo => {:default => "FOO"} }
|
58
|
+
style.get_option("foo").value => "FOO"
|
59
|
+
|
60
|
+
=== Persisting options specific to a record
|
61
|
+
|
62
|
+
You can persist numeric, boolean, or string values for storage.
|
63
|
+
|
64
|
+
style.set_option("color", "red")
|
65
|
+
style.get_option("color").value => "red"
|
66
|
+
|
67
|
+
style.set_option("active", false)
|
68
|
+
style.get_option("active").value => false
|
69
|
+
|
70
|
+
style.set_option("max_time", 3600)
|
71
|
+
style.get_option("max_time").value => 3600
|
72
|
+
|
73
|
+
=== Option precedence
|
74
|
+
|
75
|
+
Options are preferred in the following order:
|
76
|
+
|
77
|
+
1. Stored options specific for this record
|
78
|
+
2. Runtime options provided to the instance
|
79
|
+
3. Class options specified at load time.
|
80
|
+
|
81
|
+
Example:
|
82
|
+
|
83
|
+
class StyleWithDefaults < ActiveRecord::Base
|
84
|
+
acts_as_optionable
|
85
|
+
|
86
|
+
specify_option :background_color, :default => "white"
|
87
|
+
specify_option :color, :default => "black"
|
88
|
+
end
|
89
|
+
|
90
|
+
style = StyleWithDefaults.create
|
91
|
+
style.instance_specified_options = { :color => { :default => "green" } }
|
92
|
+
style.get_option("background_color").value => "white"
|
93
|
+
style.get_option("color").value => "green"
|
94
|
+
style.set_option("color", "blue")
|
95
|
+
style.get_option("color").value => "blue"
|
96
|
+
|
97
|
+
|
98
|
+
=== Easy options and values retrieval
|
99
|
+
|
100
|
+
Use #options_values_struct to grab a struct to allow for method based calls for all default and set options:
|
101
|
+
|
102
|
+
style = StyleWithDefaults.create
|
103
|
+
options = style.options_values_struct
|
104
|
+
options.color => "black"
|
105
|
+
|
106
|
+
This is useful, for instance, for passing a set of options into a liquid template.
|
107
|
+
|
108
|
+
== TODO
|
109
|
+
|
110
|
+
* Thinking about finding a way to optionally associate the option with an asset table. This would be useful for allowing user defined stylesheet options referencing S3 assets.
|
111
|
+
* Add in a way to return an option value straight away.
|
112
|
+
* Assign multiple settings at a time.
|
113
|
+
|
114
|
+
|
115
|
+
|
116
|
+
Copyright (c) 2010 Brendon Murphy, released under the MIT license
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.1.1
|
@@ -15,6 +15,7 @@ module ActiveRecord
|
|
15
15
|
end
|
16
16
|
|
17
17
|
module IntanceMethods
|
18
|
+
# Store an option persistently and override default option
|
18
19
|
def set_option(name, value)
|
19
20
|
option = get_stored_option(name) || options.build(:name => name.to_s)
|
20
21
|
return if new_option_matches_current?(option)
|
@@ -24,19 +25,13 @@ module ActiveRecord
|
|
24
25
|
ret
|
25
26
|
end
|
26
27
|
|
28
|
+
# Get a stored option, or fall back to a default option
|
27
29
|
def get_option(name)
|
28
30
|
get_stored_option(name) ||
|
29
31
|
get_default_option(name)
|
30
|
-
end
|
31
|
-
|
32
|
-
def get_default_option(name)
|
33
|
-
instance_specified_option(name) || self.class.get_specified_option(name)
|
34
|
-
end
|
35
|
-
|
36
|
-
def get_default_options
|
37
|
-
self.class.optionable_specified_options.merge(instance_specified_options || {})
|
38
|
-
end
|
32
|
+
end
|
39
33
|
|
34
|
+
# Delete a stored option.
|
40
35
|
def delete_option(name)
|
41
36
|
if option = options(:reload).find_by_name(name.to_s)
|
42
37
|
option = option.destroy
|
@@ -46,26 +41,53 @@ module ActiveRecord
|
|
46
41
|
end
|
47
42
|
|
48
43
|
def options_and_defaults
|
49
|
-
options_as_hash = options.inject({}) do |memo, option|
|
50
|
-
memo[option.name.to_s] = option
|
51
|
-
memo
|
52
|
-
end
|
53
44
|
get_default_options.merge(options_as_hash)
|
54
45
|
end
|
55
|
-
|
56
|
-
def specified_options
|
57
|
-
raise "TODO"
|
58
|
-
end
|
59
46
|
|
47
|
+
# Returns an instance of options where option names are callable as methods
|
48
|
+
#
|
49
|
+
# Example:
|
50
|
+
# # Where foo is 'FOO' & bar is 'BAR'
|
51
|
+
# options = foo.options_values_struct
|
52
|
+
# options.foo => "FOO"
|
53
|
+
# options.bar => "BAR"
|
54
|
+
def options_values_struct
|
55
|
+
options = {}
|
56
|
+
options_and_defaults.each do |name, option|
|
57
|
+
options[name.to_s] = option.value
|
58
|
+
end
|
59
|
+
OpenStruct.new(options)
|
60
|
+
end
|
61
|
+
|
60
62
|
protected
|
61
63
|
|
64
|
+
# Gets the default option if set. Prefers instance default over class default.
|
65
|
+
def get_default_option(name)
|
66
|
+
instance_specified_option(name) || self.class.get_specified_option(name)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Get a hash of all default options, with option names as keys.
|
70
|
+
def get_default_options
|
71
|
+
self.class.optionable_specified_options.merge(instance_specified_options || {})
|
72
|
+
end
|
73
|
+
|
74
|
+
# Find the stored option in the database
|
62
75
|
def get_stored_option(name)
|
63
76
|
options.detect { |option| option.name.to_s == name.to_s }
|
64
77
|
end
|
65
78
|
|
79
|
+
# Check if a new value provided is the same as the default option.
|
66
80
|
def new_option_matches_current?(option)
|
67
81
|
(!option.new_record? && option.value == value) || (get_default_option(name).value == value rescue nil)
|
68
82
|
end
|
83
|
+
|
84
|
+
# Return the stored options as a hash, with the option names as keys.
|
85
|
+
def options_as_hash
|
86
|
+
options.inject({}) do |memo, option|
|
87
|
+
memo[option.name.to_s] = option
|
88
|
+
memo
|
89
|
+
end
|
90
|
+
end
|
69
91
|
end
|
70
92
|
end
|
71
93
|
end
|
@@ -3,14 +3,17 @@ module ActiveRecord
|
|
3
3
|
module Optionable
|
4
4
|
module SpecifyOption
|
5
5
|
module ClassMethods
|
6
|
+
# Setup a default value at the class level.
|
6
7
|
def specify_option(option_name, opts = {})
|
7
8
|
optionable_specified_options[option_name.to_s] = Option.new_readonly(:name => option_name.to_s, :default => opts[:default])
|
8
9
|
end
|
9
10
|
|
11
|
+
# Returns a hash of options specified at the class level
|
10
12
|
def optionable_specified_options
|
11
13
|
@optionable_specified_options ||= {}
|
12
14
|
end
|
13
15
|
|
16
|
+
# Get an option specified at the class level.
|
14
17
|
def get_specified_option(option_name)
|
15
18
|
optionable_specified_options[option_name.to_s]
|
16
19
|
end
|
@@ -19,12 +22,20 @@ module ActiveRecord
|
|
19
22
|
module InstanceMethods
|
20
23
|
attr_reader :instance_specified_options
|
21
24
|
|
25
|
+
# Return an option specified for this instance
|
22
26
|
def instance_specified_option(option_name)
|
23
27
|
instance_specified_options[option_name.to_s] if instance_specified_options
|
24
28
|
end
|
25
29
|
|
30
|
+
# Setup instance options. Pass in a hash of options as such:
|
31
|
+
# instance_options = {
|
32
|
+
# :foo => { :default => "FOO" },
|
33
|
+
# :bar => { :default => "BAR" }
|
34
|
+
# }
|
35
|
+
# foo.instance_specified_options = instance_options
|
36
|
+
#
|
37
|
+
# These options only persist in the instance, and aren't stored to database.
|
26
38
|
def instance_specified_options=(opts)
|
27
|
-
opts.symbolize_keys!
|
28
39
|
@instance_specified_options = {}
|
29
40
|
opts.each do |option_name, attributes|
|
30
41
|
attributes.symbolize_keys!
|
@@ -63,7 +63,7 @@ describe "ActsAsOptionable" do
|
|
63
63
|
|
64
64
|
describe "specifying options at class level" do
|
65
65
|
it "should have the proper number of options set" do
|
66
|
-
@optionable.
|
66
|
+
@optionable.options_and_defaults.keys.length.should == 2
|
67
67
|
end
|
68
68
|
|
69
69
|
it "should have the expected options set" do
|
@@ -229,4 +229,25 @@ describe "ActsAsOptionable" do
|
|
229
229
|
end
|
230
230
|
end
|
231
231
|
end
|
232
|
+
|
233
|
+
describe "fetching an object with option names and values" do
|
234
|
+
it "should have a method to fetch option names and values" do
|
235
|
+
lambda { @optionable.options_values_struct }.should_not raise_error(NoMethodError)
|
236
|
+
end
|
237
|
+
|
238
|
+
it "should return an object that lets us retreive values by calling a method named for the option" do
|
239
|
+
option_values = @optionable.options_values_struct
|
240
|
+
option_values.foo.should == "FOOFOO"
|
241
|
+
option_values.bar.should == "BARBAR"
|
242
|
+
end
|
243
|
+
|
244
|
+
it "should contain both set and default options" do
|
245
|
+
@optionable.instance_specified_options = @options_template
|
246
|
+
@optionable.set_option("example_option", 99)
|
247
|
+
option_values = @optionable.options_values_struct
|
248
|
+
option_values.foo.should == "FOOFOO"
|
249
|
+
option_values.fizz.should == "FIZZFIZZ"
|
250
|
+
option_values.example_option.should == 99
|
251
|
+
end
|
252
|
+
end
|
232
253
|
end
|
data/spec/spec.opts
ADDED
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 1
|
8
|
+
- 1
|
9
|
+
version: 0.1.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Brendon Murphy
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-04-
|
17
|
+
date: 2010-04-23 00:00:00 -07:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|
@@ -25,10 +25,10 @@ executables: []
|
|
25
25
|
extensions: []
|
26
26
|
|
27
27
|
extra_rdoc_files:
|
28
|
-
- README
|
28
|
+
- README.rdoc
|
29
29
|
files:
|
30
30
|
- MIT-LICENSE
|
31
|
-
- README
|
31
|
+
- README.rdoc
|
32
32
|
- Rakefile
|
33
33
|
- VERSION
|
34
34
|
- lib/acts-as-optionable.rb
|
@@ -38,6 +38,7 @@ files:
|
|
38
38
|
- lib/acts_as_optionable/specify_option.rb
|
39
39
|
- rails/init.rb
|
40
40
|
- spec/acts_as_optionable_spec.rb
|
41
|
+
- spec/spec.opts
|
41
42
|
- spec/spec_helper.rb
|
42
43
|
has_rdoc: true
|
43
44
|
homepage: http://github.com/bemurphy/acts_as_optionable
|
data/README
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
ActsAsOptionable
|
2
|
-
================
|
3
|
-
|
4
|
-
I don't recommend using this yet since I'm going to make a couple core changes shortly. Very alpha.
|
5
|
-
|
6
|
-
|
7
|
-
Example
|
8
|
-
=======
|
9
|
-
|
10
|
-
Example goes here.
|
11
|
-
|
12
|
-
|
13
|
-
Copyright (c) 2010 [name of plugin creator], released under the MIT license
|