acts-as-optionable 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 [name of plugin creator]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,13 @@
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
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ require 'rake'
2
+ require 'rake/rdoctask'
3
+ require 'spec/rake/spectask'
4
+
5
+ begin
6
+ require 'jeweler'
7
+ Jeweler::Tasks.new do |gemspec|
8
+ gemspec.name = "acts-as-optionable"
9
+ gemspec.summary = "ActsAsOptionable is a plugin for Rails that support adding options, as well as specify default options, to ActiveRecord models."
10
+ gemspec.description = "Add options to ActiveRecord models. I don't advise using this yet, as it's very alpha."
11
+ gemspec.email = "xternal1+aao@gmail.com"
12
+ gemspec.homepage = "http://github.com/bemurphy/acts_as_optionable"
13
+ gemspec.authors = ["Brendon Murphy"]
14
+ gemspec.files = FileList["[A-Z]*", "{lib,spec,rails}/**/*"] - FileList["**/*.log"]
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
19
+ end
20
+
21
+ desc 'Generate documentation for the acts_as_optionable plugin.'
22
+ Rake::RDocTask.new(:rdoc) do |rdoc|
23
+ rdoc.rdoc_dir = 'rdoc'
24
+ rdoc.title = 'ActsAsOptionable'
25
+ rdoc.options << '--line-numbers' << '--inline-source'
26
+ rdoc.rdoc_files.include('README')
27
+ rdoc.rdoc_files.include('lib/**/*.rb')
28
+ end
29
+
30
+ desc 'Default: run specs'
31
+ task :default => :spec
32
+ Spec::Rake::SpecTask.new do |t|
33
+ t.spec_files = FileList["spec/**/*_spec.rb"]
34
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
@@ -0,0 +1,3 @@
1
+ require "acts_as_optionable/acts_as_optionable"
2
+ require "acts_as_optionable/option_methods"
3
+ require "acts_as_optionable/specify_option"
@@ -0,0 +1,72 @@
1
+ module ActiveRecord
2
+ module Acts
3
+ module Optionable
4
+ def self.included(base)
5
+ base.extend ClassMethods
6
+ end
7
+
8
+ module ClassMethods
9
+ def acts_as_optionable
10
+ has_many :options, :as => :optionable, :dependent => :destroy
11
+ include IntanceMethods
12
+ extend ActiveRecord::Acts::Optionable::SpecifyOption::ClassMethods
13
+ include ActiveRecord::Acts::Optionable::SpecifyOption::InstanceMethods
14
+ end
15
+ end
16
+
17
+ module IntanceMethods
18
+ def set_option(name, value)
19
+ option = get_stored_option(name) || options.build(:name => name.to_s)
20
+ return if new_option_matches_current?(option)
21
+ option.value = value
22
+ ret = option.save!
23
+ options(:reload)
24
+ ret
25
+ end
26
+
27
+ def get_option(name)
28
+ get_stored_option(name) ||
29
+ 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
39
+
40
+ def delete_option(name)
41
+ if option = options(:reload).find_by_name(name.to_s)
42
+ option = option.destroy
43
+ options(:reload)
44
+ option
45
+ end
46
+ end
47
+
48
+ 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
+ get_default_options.merge(options_as_hash)
54
+ end
55
+
56
+ def specified_options
57
+ raise "TODO"
58
+ end
59
+
60
+ protected
61
+
62
+ def get_stored_option(name)
63
+ options.detect { |option| option.name.to_s == name.to_s }
64
+ end
65
+
66
+ def new_option_matches_current?(option)
67
+ (!option.new_record? && option.value == value) || (get_default_option(name).value == value rescue nil)
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,17 @@
1
+ module ActiveRecord
2
+ module Acts
3
+ module Optionable
4
+ module OptionMethods
5
+ def self.included(option_model)
6
+ option_model.extend Finders
7
+ end
8
+
9
+ module Finders
10
+ def find_options_for_optionable(optionable_str, optionable_id)
11
+ all(:conditions => { :optionable_type => optionable_str, :optionable_id => optionable_id }, :order => "created_at DESC")
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ # module ActiveRecord
2
+ # module Acts
3
+ # module Optionable
4
+ # module SpecifyOption
5
+ # class OptionsTemplate
6
+ # def initialize(template_hash = {})
7
+ #
8
+ # end
9
+ # end
10
+ # end
11
+ # end
12
+ # end
13
+ # end
@@ -0,0 +1,38 @@
1
+ module ActiveRecord
2
+ module Acts
3
+ module Optionable
4
+ module SpecifyOption
5
+ module ClassMethods
6
+ def specify_option(option_name, opts = {})
7
+ optionable_specified_options[option_name.to_s] = Option.new_readonly(:name => option_name.to_s, :default => opts[:default])
8
+ end
9
+
10
+ def optionable_specified_options
11
+ @optionable_specified_options ||= {}
12
+ end
13
+
14
+ def get_specified_option(option_name)
15
+ optionable_specified_options[option_name.to_s]
16
+ end
17
+ end
18
+
19
+ module InstanceMethods
20
+ attr_reader :instance_specified_options
21
+
22
+ def instance_specified_option(option_name)
23
+ instance_specified_options[option_name.to_s] if instance_specified_options
24
+ end
25
+
26
+ def instance_specified_options=(opts)
27
+ opts.symbolize_keys!
28
+ @instance_specified_options = {}
29
+ opts.each do |option_name, attributes|
30
+ attributes.symbolize_keys!
31
+ @instance_specified_options[option_name.to_s] = Option.new_readonly(:name => option_name, :default => attributes[:default])
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
data/rails/init.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "acts-as-optionable"
2
+
3
+ ActiveRecord::Base.send(:include, ActiveRecord::Acts::Optionable)
4
+
5
+ RAILS_DEFAULT_LOGGER.info "** acts_as_optionable: initialized properly."
@@ -0,0 +1,232 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
4
+
5
+ class Mixin < ActiveRecord::Base
6
+ end
7
+
8
+ class SpecifiedMixin < Mixin
9
+ acts_as_optionable
10
+
11
+ specify_option :foo, :default => "FOOFOO"
12
+ specify_option :bar, :default => "BARBAR"
13
+ end
14
+
15
+ class NoSpecifiedMixin < Mixin
16
+ acts_as_optionable
17
+ end
18
+
19
+ # Don't want output from AR
20
+ $stdout = StringIO.new
21
+
22
+ def setup_db
23
+ ActiveRecord::Base.logger
24
+ ActiveRecord::Schema.define do
25
+ create_table :mixins do |t|
26
+ t.string :value
27
+ end
28
+
29
+ create_table :options do |t|
30
+ t.string :name
31
+ t.string :value
32
+ t.references :optionable, :polymorphic => true
33
+ t.timestamps
34
+ end
35
+
36
+ end
37
+ end
38
+
39
+ def teardown_db
40
+ ActiveRecord::Base.connection.tables.each do |table|
41
+ ActiveRecord::Base.connection.drop_table(table)
42
+ end
43
+ end
44
+
45
+ describe "ActsAsOptionable" do
46
+ before(:all) do
47
+ setup_db
48
+ end
49
+
50
+ after(:all) do
51
+ teardown_db
52
+ end
53
+
54
+ after(:each) do
55
+ Option.delete_all
56
+ Mixin.delete_all
57
+ end
58
+
59
+ before(:each) do
60
+ @optionable = SpecifiedMixin.create!
61
+ @options_template = { :fizz => { :default => "FIZZFIZZ" }, :buzz => { :default => "BUZZBUZZ" } }
62
+ end
63
+
64
+ describe "specifying options at class level" do
65
+ it "should have the proper number of options set" do
66
+ @optionable.get_default_options.length.should == 2
67
+ end
68
+
69
+ it "should have the expected options set" do
70
+ @optionable.get_option(:foo).value.should == "FOOFOO"
71
+ @optionable.get_option(:bar).value.should == "BARBAR"
72
+ end
73
+
74
+ it "should not mix specifications across unrelated classes" do
75
+ class Foobar < Mixin
76
+ acts_as_optionable
77
+ specify_option :foobar, :default => "FOOBAR"
78
+ end
79
+
80
+ foobar = Foobar.create!
81
+ foobar.get_option(:foobar).value.should == "FOOBAR"
82
+ Foobar.optionable_specified_options.should_not have_key("foo")
83
+ Foobar.optionable_specified_options.should_not have_key("bar")
84
+ end
85
+
86
+ it "should return readonly records for the default options" do
87
+ @optionable.get_option(:foo).should be_readonly
88
+ end
89
+ end
90
+
91
+ describe "specifying options at the instance level" do
92
+ before(:each) do
93
+ @optionable = NoSpecifiedMixin.create!
94
+ end
95
+
96
+ it "should allow setting the options" do
97
+ lambda {
98
+ @optionable.instance_specified_options = @options_template
99
+ }.should_not raise_error
100
+ end
101
+
102
+ it "should have the expected default options" do
103
+ @optionable.instance_specified_options = @options_template
104
+ @optionable.get_option(:fizz).value.should == "FIZZFIZZ"
105
+ @optionable.get_option(:buzz).value.should == "BUZZBUZZ"
106
+ end
107
+
108
+ it "should return readonly records for the default options" do
109
+ @optionable.instance_specified_options = @options_template
110
+ @optionable.get_option(:fizz).should be_readonly
111
+ end
112
+ end
113
+
114
+ describe "default option precedence" do
115
+ before(:each) do
116
+ @optionable.instance_specified_options = @options_template.merge(:bar => {:default => "INSTANCE"}, :fizzbuzz => { :default => "FIZZBUZZ"})
117
+ end
118
+
119
+ it "should use class level defaults if an instance level doesn't exist" do
120
+ @optionable.get_option(:bar).value.should == "INSTANCE"
121
+ end
122
+
123
+ it "should use instance level regardless of state of class level default" do
124
+ @optionable.get_option(:fizzbuzz).value.should == "FIZZBUZZ"
125
+ end
126
+
127
+ it "should be nil if no default is set" do
128
+ @optionable.get_option(:bogus).should be_nil
129
+ end
130
+ end
131
+
132
+ describe "working with stored options" do
133
+ before(:each) do
134
+ @key = :is_something
135
+ end
136
+
137
+ describe "storing options" do
138
+ it "should be able to store a number" do
139
+ @optionable.set_option(@key, 9876)
140
+ @optionable.get_option(@key).value.should == 9876
141
+ end
142
+
143
+ it "should be able to store false" do
144
+ @optionable.set_option(@key, false)
145
+ @optionable.get_option(@key).value.class.should == FalseClass
146
+ end
147
+
148
+ it "should be able to store true" do
149
+ @optionable.set_option(@key, true)
150
+ @optionable.get_option(@key).value.class.should == TrueClass
151
+ end
152
+
153
+ it "should be able to store a string" do
154
+ @optionable.set_option(@key, "a-string")
155
+ @optionable.get_option(@key).value.should == "a-string"
156
+ end
157
+
158
+ it "should raise an exception if you try to store an unapproved type" do
159
+ lambda { @optionable.set_option(@key, {:a => "b"}) }.should raise_error(ArgumentError)
160
+ end
161
+
162
+ it "should create a new option if one didn't already exist" do
163
+ @optionable.set_option(@key, true)
164
+ lambda {@optionable.set_option(:new_option, "new-option") }.should change { Option.count }.by(1)
165
+ end
166
+
167
+ it "should not insert a new option if it already exists" do
168
+ @optionable.set_option(@key, true)
169
+ lambda {@optionable.set_option(@key, false) }.should_not change { Option.count }
170
+ end
171
+
172
+ it "should overwrite the option if it already exists" do
173
+ @optionable.set_option(@key, true)
174
+ @optionable.get_option(@key).value.should be_true
175
+ @optionable.set_option(@key, false)
176
+ @optionable.get_option(@key).value.should be_false
177
+ end
178
+ end
179
+
180
+ describe "getting options" do
181
+ it "should prefer the stored option over a default class option" do
182
+ @optionable.class.optionable_specified_options.should have_key("foo")
183
+ n = rand(999)
184
+ @optionable.set_option("foo", n)
185
+ @optionable.get_option("foo").value.should == n
186
+ end
187
+
188
+ it "should prefer the stored option over a default instance option" do
189
+ n = rand(999)
190
+ @optionable.instance_specified_options = @options_template.merge(:foo => { :default => n })
191
+ @optionable.get_option("foo").value.should == n
192
+ j = rand(999)
193
+ @optionable.set_option("foo", j)
194
+ @optionable.get_option("foo").value.should == j
195
+ end
196
+ end
197
+
198
+ describe "deleting options" do
199
+ before(:each) do
200
+ @key = :delete_me
201
+ @optionable.set_option(@key, "delete-me")
202
+ end
203
+
204
+ it "should remove a row from the options" do
205
+ lambda { @optionable.delete_option(@key) }.should change { Option.count }.by(-1)
206
+ end
207
+
208
+ it "should delete the option" do
209
+ @optionable.get_option(@key).value.should == "delete-me"
210
+ @optionable.delete_option(@key)
211
+ @optionable.get_option(@key).should be_nil
212
+ end
213
+
214
+ it "should not impact a default class option" do
215
+ @optionable.get_option("foo").value.should == "FOOFOO"
216
+ @optionable.set_option("foo", "foofoo")
217
+ @optionable.get_option("foo").value.should == "foofoo"
218
+ @optionable.delete_option("foo")
219
+ @optionable.get_option("foo").value.should == "FOOFOO"
220
+ end
221
+
222
+ it "should not impact a default instance option" do
223
+ @optionable.instance_specified_options = @options_template
224
+ @optionable.get_option("fizz").value.should == "FIZZFIZZ"
225
+ @optionable.set_option("fizz", "fizzfizz")
226
+ @optionable.get_option("fizz").value.should == "fizzfizz"
227
+ @optionable.delete_option("fizz")
228
+ @optionable.get_option("fizz").value.should == "FIZZFIZZ"
229
+ end
230
+ end
231
+ end
232
+ end
@@ -0,0 +1,10 @@
1
+ begin
2
+ require File.dirname(__FILE__) + '/../../../../spec/spec_helper'
3
+ rescue LoadError
4
+ puts "You need to install rspec in your base app"
5
+ exit
6
+ end
7
+
8
+ plugin_spec_dir = File.dirname(__FILE__)
9
+ ActiveRecord::Base.logger = Logger.new(plugin_spec_dir + "/debug.log")
10
+
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: acts-as-optionable
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 0
9
+ version: 0.0.0
10
+ platform: ruby
11
+ authors:
12
+ - Brendon Murphy
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-04-22 00:00:00 -07:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: Add options to ActiveRecord models. I don't advise using this yet, as it's very alpha.
22
+ email: xternal1+aao@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files:
28
+ - README
29
+ files:
30
+ - MIT-LICENSE
31
+ - README
32
+ - Rakefile
33
+ - VERSION
34
+ - lib/acts-as-optionable.rb
35
+ - lib/acts_as_optionable/acts_as_optionable.rb
36
+ - lib/acts_as_optionable/option_methods.rb
37
+ - lib/acts_as_optionable/options_template.rb
38
+ - lib/acts_as_optionable/specify_option.rb
39
+ - rails/init.rb
40
+ - spec/acts_as_optionable_spec.rb
41
+ - spec/spec_helper.rb
42
+ has_rdoc: true
43
+ homepage: http://github.com/bemurphy/acts_as_optionable
44
+ licenses: []
45
+
46
+ post_install_message:
47
+ rdoc_options:
48
+ - --charset=UTF-8
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 0
57
+ version: "0"
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ requirements: []
66
+
67
+ rubyforge_project:
68
+ rubygems_version: 1.3.6
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: ActsAsOptionable is a plugin for Rails that support adding options, as well as specify default options, to ActiveRecord models.
72
+ test_files:
73
+ - spec/acts_as_optionable_spec.rb
74
+ - spec/spec_helper.rb