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 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.0.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.get_default_options.length.should == 2
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
@@ -0,0 +1,5 @@
1
+ --colour
2
+ --format progress
3
+ --loadby mtime
4
+ --reverse
5
+ --drb
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 0
8
- - 0
9
- version: 0.0.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-22 00:00:00 -07:00
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