acts_as_acts_as 0.0.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.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +18 -0
- data/Rakefile +45 -0
- data/VERSION +1 -0
- data/lib/acts_as_acts_as/group_macros.rb +60 -0
- data/lib/acts_as_acts_as/macros.rb +86 -0
- data/lib/acts_as_acts_as/requirements/collector.rb +48 -0
- data/lib/acts_as_acts_as/requirements/verifier.rb +75 -0
- data/lib/acts_as_acts_as/requirements.rb +3 -0
- data/lib/acts_as_acts_as.rb +15 -0
- data/spec/acts_as_acts_as_spec.rb +7 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +9 -0
- metadata +82 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 phinze
|
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.rdoc
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
= acts_as_acts_as
|
2
|
+
|
3
|
+
Description goes here.
|
4
|
+
|
5
|
+
== Note on Patches/Pull Requests
|
6
|
+
|
7
|
+
* Fork the project.
|
8
|
+
* Make your feature addition or bug fix.
|
9
|
+
* Add tests for it. This is important so I don't break it in a
|
10
|
+
future version unintentionally.
|
11
|
+
* Commit, do not mess with rakefile, version, or history.
|
12
|
+
(if you want to have your own version, that is fine but
|
13
|
+
bump version in a commit by itself I can ignore when I pull)
|
14
|
+
* Send me a pull request. Bonus points for topic branches.
|
15
|
+
|
16
|
+
== Copyright
|
17
|
+
|
18
|
+
Copyright (c) 2009 phinze. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "acts_as_acts_as"
|
8
|
+
gem.summary = %Q{Testing harness for acts_as plugins}
|
9
|
+
gem.description = %Q{Generate temporary tables and models, specify defined
|
10
|
+
and required methods, all sorts of fun stuff!}
|
11
|
+
gem.email = "paul.t.hinze@gmail.com"
|
12
|
+
gem.homepage = "http://github.com/phinze/acts_as_acts_as"
|
13
|
+
gem.authors = ["phinze"]
|
14
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
15
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
16
|
+
end
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'spec/rake/spectask'
|
22
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
23
|
+
spec.libs << 'lib' << 'spec'
|
24
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
25
|
+
end
|
26
|
+
|
27
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
28
|
+
spec.libs << 'lib' << 'spec'
|
29
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
30
|
+
spec.rcov = true
|
31
|
+
end
|
32
|
+
|
33
|
+
task :spec => :check_dependencies
|
34
|
+
|
35
|
+
task :default => :spec
|
36
|
+
|
37
|
+
require 'rake/rdoctask'
|
38
|
+
Rake::RDocTask.new do |rdoc|
|
39
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
40
|
+
|
41
|
+
rdoc.rdoc_dir = 'rdoc'
|
42
|
+
rdoc.title = "acts_as_acts_as #{version}"
|
43
|
+
rdoc.rdoc_files.include('README*')
|
44
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
45
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Methods available _at the same level as_ examples, including methods that
|
2
|
+
# themselves define examples, before, and after blocks
|
3
|
+
module ActsAsActsAs::GroupMacros
|
4
|
+
|
5
|
+
# Example Usage:
|
6
|
+
# acts_as :acts_as_billable do |plugin|
|
7
|
+
# plugin.should require_methods(
|
8
|
+
# :billable_amount,
|
9
|
+
# :billable_description,
|
10
|
+
# :billable_type,
|
11
|
+
# :billable_user,
|
12
|
+
# :billable_mfk
|
13
|
+
# )
|
14
|
+
# plugin.should define_methods(
|
15
|
+
# :billed?
|
16
|
+
# )
|
17
|
+
# plugin.with(:bill_by_date => true).should require_columns(
|
18
|
+
# [:effective_start_date, :datetime],
|
19
|
+
# [:effective_end_date, :datetime],
|
20
|
+
# [:quantity, :integer]
|
21
|
+
# )
|
22
|
+
# end
|
23
|
+
def acts_as(acts_as_method, &block)
|
24
|
+
# Now use our new object to let the block build up requirements
|
25
|
+
collector = ActsAsActsAs::RequirementsCollector.new
|
26
|
+
yield collector
|
27
|
+
|
28
|
+
|
29
|
+
describe "Acts As Plugin #{acts_as_method}" do
|
30
|
+
|
31
|
+
verifier.verify_requirements(acts_as_method, collector)
|
32
|
+
end
|
33
|
+
|
34
|
+
before(:all) do
|
35
|
+
|
36
|
+
ActsAsBillable::BillableObjects.classes_using_billing = []
|
37
|
+
|
38
|
+
@valid_model = tableless_model(
|
39
|
+
:columns => collector.all_requirements[:require_columns],
|
40
|
+
:methods => collector.all_requirements[:require_methods]
|
41
|
+
)
|
42
|
+
|
43
|
+
@valid_model.send(acts_as_method)
|
44
|
+
|
45
|
+
@model_opts = {
|
46
|
+
:columns => collector.all_requirements[:require_columns],
|
47
|
+
:methods => collector.all_requirements[:require_methods]
|
48
|
+
}
|
49
|
+
|
50
|
+
@valid_model_with_table = temp_model(@model_opts)
|
51
|
+
@valid_model_with_table.send(acts_as_method)
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
after(:all) do
|
56
|
+
drop_temp_model(@valid_model_with_table)
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# Methods available _within_ examples
|
2
|
+
module ActsAsActsAs::Macros
|
3
|
+
|
4
|
+
# ActsAsActsAs::Macros#tableless_model a factory method for an ActiveRecord
|
5
|
+
# model using the 'active_record_tableless' plugin.
|
6
|
+
#
|
7
|
+
# ==== Parameters
|
8
|
+
# * <tt>:class_name</tt> - if you want the class to be assigned a constant,
|
9
|
+
# specify it as a string here, note that if you want
|
10
|
+
# the constant to be namespaced you should do the
|
11
|
+
# nested const_sets yourself and leave this option
|
12
|
+
# blank
|
13
|
+
# * <tt>:superclass</tt> - superclass for the new model, defaults to
|
14
|
+
# ActiveRecord::Base, as you might expect
|
15
|
+
# * <tt>:columns</tt> - collection of tuples as expected by the
|
16
|
+
# <tt>active_record_tableless</tt> plugin to be
|
17
|
+
# added as columns to the created model
|
18
|
+
# * <tt>:methods</tt> - collection of symbols to define by attr_accessor
|
19
|
+
# in the created model
|
20
|
+
def tableless_model(options)
|
21
|
+
options = options.dup
|
22
|
+
class_name = options.delete(:class_name) || nil
|
23
|
+
superclass = options.delete(:superclass) || ActiveRecord::Base
|
24
|
+
columns = options.delete(:columns) || []
|
25
|
+
methods = options.delete(:methods) || []
|
26
|
+
|
27
|
+
newclass = Class.new(superclass)
|
28
|
+
|
29
|
+
newclass.class_eval do
|
30
|
+
tableless :columns => columns
|
31
|
+
methods.each do |m|
|
32
|
+
attr_accessor m
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
Object.const_set(class_name, newclass) if class_name
|
37
|
+
return newclass
|
38
|
+
end
|
39
|
+
|
40
|
+
# A model with a table that exists only for the duration of the block, or if
|
41
|
+
# no block is passed, until <tt>drop_temp_model</tt> is called
|
42
|
+
def temp_model(model_opts, &block)
|
43
|
+
t = Time.now
|
44
|
+
uid = t.to_i.to_s + t.usec.to_s
|
45
|
+
table_name = "temp_table_#{uid}"
|
46
|
+
ActiveRecord::Base.connection.create_table(table_name) do |t|
|
47
|
+
model_opts[:columns].each do |name, type|
|
48
|
+
t.send(type, name)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
newclass = Class.new(ActiveRecord::Base)
|
53
|
+
Object.const_set(table_name.camelize, newclass)
|
54
|
+
newclass.set_table_name table_name
|
55
|
+
newclass.reset_column_information
|
56
|
+
|
57
|
+
newclass.class_eval do
|
58
|
+
model_opts[:methods].each do |m|
|
59
|
+
attr_accessor m
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
return newclass unless block_given?
|
64
|
+
|
65
|
+
yield newclass
|
66
|
+
|
67
|
+
drop_temp_model(newclass)
|
68
|
+
end
|
69
|
+
|
70
|
+
def temp_versioned_model(model_opts, &block)
|
71
|
+
model = temp_model(model_opts)
|
72
|
+
silence_stream(STDERR) { model.acts_as_ris_versioned(model_opts[:aav_options] || {}) }
|
73
|
+
model.update_versioned_table
|
74
|
+
|
75
|
+
return model unless block_given?
|
76
|
+
yield model
|
77
|
+
drop_temp_model(model)
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
def drop_temp_model(tmodel)
|
82
|
+
ActiveRecord::Base.connection.drop_table(tmodel.table_name)
|
83
|
+
ActiveRecord::Base.connection.drop_table(tmodel.versioned_table_name) if tmodel.respond_to?(:versioned_table_name)
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# A specialized object we pass into the block of `acts_as` so the DSL is nice
|
2
|
+
# and pretty. It basically just builds a hash of requirements matchers.
|
3
|
+
class ActsAsActsAs::Requirements::Collector
|
4
|
+
attr_accessor :requirements, :options_collectors, :options
|
5
|
+
|
6
|
+
def initialize(options={})
|
7
|
+
@requirements = {}
|
8
|
+
@options_collectors = []
|
9
|
+
@options = options
|
10
|
+
|
11
|
+
# run into nil problems with temp_model if require_columns is nil
|
12
|
+
@requirements[:require_columns] = []
|
13
|
+
end
|
14
|
+
|
15
|
+
# Should just add the results of calling a matcher (i.e. the returned
|
16
|
+
# hash) to the list of requirements
|
17
|
+
def should(matcher)
|
18
|
+
raise "Bad Matcher" unless matcher.is_a?(Array) and matcher.length == 2
|
19
|
+
key, args = matcher
|
20
|
+
@requirements[key] = (@requirements.key?(key)) ? @requirements[key] + args : args
|
21
|
+
end
|
22
|
+
|
23
|
+
# spin off a duplicate collector with the extra options specified
|
24
|
+
def with(options)
|
25
|
+
@options_collectors << self.class.new(options)
|
26
|
+
@options_collectors.last.requirements = self.requirements.dup # dup important so my reqs don't change
|
27
|
+
return @options_collectors.last
|
28
|
+
end
|
29
|
+
|
30
|
+
# Convenience method for getting the whole tree of
|
31
|
+
# collectors that may have been spawned off via `with`
|
32
|
+
def all
|
33
|
+
return [self] + @options_collectors.inject([]) { |a, c| a + c.all }
|
34
|
+
end
|
35
|
+
|
36
|
+
def all_requirements
|
37
|
+
all.inject({}) { |h, c| h.merge(c.requirements) }
|
38
|
+
end
|
39
|
+
|
40
|
+
class Context
|
41
|
+
[:require_methods, :require_columns, :define_methods, :define_class_methods].each do |x|
|
42
|
+
define_method x { |*args| [x, args] }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def collect(&block)
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
class ActsAsActsAs::Requirements::Verifier
|
2
|
+
|
3
|
+
attr_accessor :acts_as_method
|
4
|
+
|
5
|
+
def initialize(acts_as_method)
|
6
|
+
@acts_as_method = acts_as_method
|
7
|
+
end
|
8
|
+
|
9
|
+
def verify_requirements(collector)
|
10
|
+
collector.all.each do |c|
|
11
|
+
describe "with options: #{c.options.inspect}" do
|
12
|
+
c.requirements.each_pair do |method, args|
|
13
|
+
send(method, acts_as_method, c.options, c.requirements, *args)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def require_methods(options, reqs, *methods)
|
20
|
+
describe 'required methods' do
|
21
|
+
methods.each do |meth|
|
22
|
+
it "#{meth} must be defined in caller" do
|
23
|
+
mod = tableless_model(
|
24
|
+
:columns => reqs[:require_methods],
|
25
|
+
:methods => reqs[:require_methods].reject { |rm| rm == meth }
|
26
|
+
)
|
27
|
+
lambda { mod.send(acts_as_method, options) }.should raise_error(/#{meth}/)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def require_columns(options, reqs, *columns)
|
34
|
+
describe 'required columns' do
|
35
|
+
columns.each do |c|
|
36
|
+
it "#{c[0]} must be defined as column in caller" do
|
37
|
+
m = tableless_model(
|
38
|
+
:columns => reqs[:require_columns].reject { |rc| rc == c },
|
39
|
+
:methods => reqs[:require_methods]
|
40
|
+
)
|
41
|
+
lambda { m.send(acts_as_method, options) }.should raise_error(/#{c[0]}/)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "#{c[0]} must be of type #{c[1]}" do
|
45
|
+
goodm = tableless_model(
|
46
|
+
:columns => reqs[:require_columns],
|
47
|
+
:methods => reqs[:require_methods]
|
48
|
+
)
|
49
|
+
badm = tableless_model(
|
50
|
+
:columns => reqs[:require_columns].map { |rc| (rc != c) ? rc : [rc[0], :badcoltype]},
|
51
|
+
:methods => reqs[:require_methods]
|
52
|
+
)
|
53
|
+
lambda { goodm.send(acts_as_method, options) }.should_not raise_error
|
54
|
+
lambda { badm.send(acts_as_method, options) }.should raise_error(/#{c[0]}/)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def define_methods(options, reqs, *methods)
|
61
|
+
describe 'defined methods' do
|
62
|
+
methods.each do |meth|
|
63
|
+
it "#{meth} method is defined automatically" do
|
64
|
+
mod = tableless_model(
|
65
|
+
:columns => reqs[:require_columns],
|
66
|
+
:methods => reqs[:require_methods]
|
67
|
+
)
|
68
|
+
lambda { mod.send(acts_as_method, options) }.should_not raise_error
|
69
|
+
mod.new.should respond_to(meth)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module ActsAsActsAs; end
|
2
|
+
|
3
|
+
require 'acts_as_acts_as/macros'
|
4
|
+
require 'acts_as_acts_as/group_macros'
|
5
|
+
|
6
|
+
# To be included from spec_helper.rb of another plugin...
|
7
|
+
# Example:
|
8
|
+
# require 'rubygems'
|
9
|
+
# require 'acts_as_acts_as'
|
10
|
+
if defined? Spec::Runner
|
11
|
+
Spec::Runner.configure do |config|
|
12
|
+
config.include ActsAsActsAs::Macros, :type => :helper
|
13
|
+
config.extend ActsAsActsAs::GroupMacros, :type => :helper
|
14
|
+
end
|
15
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: acts_as_acts_as
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- phinze
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-01-11 00:00:00 -06:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rspec
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.2.9
|
24
|
+
version:
|
25
|
+
description: |-
|
26
|
+
Generate temporary tables and models, specify defined
|
27
|
+
and required methods, all sorts of fun stuff!
|
28
|
+
email: paul.t.hinze@gmail.com
|
29
|
+
executables: []
|
30
|
+
|
31
|
+
extensions: []
|
32
|
+
|
33
|
+
extra_rdoc_files:
|
34
|
+
- LICENSE
|
35
|
+
- README.rdoc
|
36
|
+
files:
|
37
|
+
- .document
|
38
|
+
- .gitignore
|
39
|
+
- LICENSE
|
40
|
+
- README.rdoc
|
41
|
+
- Rakefile
|
42
|
+
- VERSION
|
43
|
+
- lib/acts_as_acts_as.rb
|
44
|
+
- lib/acts_as_acts_as/group_macros.rb
|
45
|
+
- lib/acts_as_acts_as/macros.rb
|
46
|
+
- lib/acts_as_acts_as/requirements.rb
|
47
|
+
- lib/acts_as_acts_as/requirements/collector.rb
|
48
|
+
- lib/acts_as_acts_as/requirements/verifier.rb
|
49
|
+
- spec/acts_as_acts_as_spec.rb
|
50
|
+
- spec/spec.opts
|
51
|
+
- spec/spec_helper.rb
|
52
|
+
has_rdoc: true
|
53
|
+
homepage: http://github.com/phinze/acts_as_acts_as
|
54
|
+
licenses: []
|
55
|
+
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options:
|
58
|
+
- --charset=UTF-8
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: "0"
|
66
|
+
version:
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: "0"
|
72
|
+
version:
|
73
|
+
requirements: []
|
74
|
+
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 1.3.5
|
77
|
+
signing_key:
|
78
|
+
specification_version: 3
|
79
|
+
summary: Testing harness for acts_as plugins
|
80
|
+
test_files:
|
81
|
+
- spec/spec_helper.rb
|
82
|
+
- spec/acts_as_acts_as_spec.rb
|