giraffesoft-attribute_fu 0.2
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/MIT-LICENSE +20 -0
- data/README +115 -0
- data/Rakefile +22 -0
- data/init.rb +2 -0
- data/lib/attribute_fu.rb +2 -0
- data/lib/attribute_fu/associated_form_helper.rb +139 -0
- data/lib/attribute_fu/associations.rb +124 -0
- data/tasks/attribute_fu_tasks.rake +4 -0
- data/test/Rakefile +10 -0
- data/test/app/controllers/application.rb +10 -0
- data/test/app/helpers/application_helper.rb +3 -0
- data/test/app/models/comment.rb +8 -0
- data/test/app/models/photo.rb +3 -0
- data/test/config/boot.rb +97 -0
- data/test/config/database.yml +15 -0
- data/test/config/environment.rb +15 -0
- data/test/config/environments/development.rb +18 -0
- data/test/config/environments/test.rb +22 -0
- data/test/config/routes.rb +35 -0
- data/test/db/migrate/001_create_photos.rb +14 -0
- data/test/db/migrate/002_create_comments.rb +15 -0
- data/test/db/schema.rb +29 -0
- data/test/script/console +3 -0
- data/test/script/destroy +3 -0
- data/test/script/generate +3 -0
- data/test/script/server +3 -0
- data/test/test/test_helper.rb +6 -0
- data/test/test/unit/associated_form_helper_test.rb +376 -0
- data/test/test/unit/comment_test.rb +6 -0
- data/test/test/unit/photo_test.rb +149 -0
- data/test/vendor/plugins/shoulda/init.rb +3 -0
- data/test/vendor/plugins/shoulda/lib/shoulda.rb +20 -0
- data/test/vendor/plugins/shoulda/lib/shoulda/active_record_helpers.rb +338 -0
- data/test/vendor/plugins/shoulda/lib/shoulda/context.rb +143 -0
- data/test/vendor/plugins/shoulda/lib/shoulda/general.rb +119 -0
- data/test/vendor/plugins/shoulda/lib/shoulda/private_helpers.rb +17 -0
- data/uninstall.rb +1 -0
- metadata +110 -0
@@ -0,0 +1,143 @@
|
|
1
|
+
module ThoughtBot # :nodoc:
|
2
|
+
module Shoulda # :nodoc:
|
3
|
+
# = context and should blocks
|
4
|
+
#
|
5
|
+
# A context block groups should statements under a common setup/teardown method.
|
6
|
+
# Context blocks can be arbitrarily nested, and can do wonders for improving the maintainability
|
7
|
+
# and readability of your test code.
|
8
|
+
#
|
9
|
+
# A context block can contain setup, should, should_eventually, and teardown blocks.
|
10
|
+
#
|
11
|
+
# class UserTest << Test::Unit::TestCase
|
12
|
+
# context "a User instance" do
|
13
|
+
# setup do
|
14
|
+
# @user = User.find(:first)
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# should "return its full name"
|
18
|
+
# assert_equal 'John Doe', @user.full_name
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# This code will produce the method <tt>"test a User instance should return its full name"</tt>.
|
24
|
+
#
|
25
|
+
# Contexts may be nested. Nested contexts run their setup blocks from out to in before each test.
|
26
|
+
# They then run their teardown blocks from in to out after each test.
|
27
|
+
#
|
28
|
+
# class UserTest << Test::Unit::TestCase
|
29
|
+
# context "a User instance" do
|
30
|
+
# setup do
|
31
|
+
# @user = User.find(:first)
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# should "return its full name"
|
35
|
+
# assert_equal 'John Doe', @user.full_name
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# context "with a profile" do
|
39
|
+
# setup do
|
40
|
+
# @user.profile = Profile.find(:first)
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# should "return true when sent :has_profile?"
|
44
|
+
# assert @user.has_profile?
|
45
|
+
# end
|
46
|
+
# end
|
47
|
+
# end
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# This code will produce the following methods
|
51
|
+
# * <tt>"test: a User instance should return its full name."</tt>
|
52
|
+
# * <tt>"test: a User instance with a profile should return true when sent :has_profile?."</tt>
|
53
|
+
#
|
54
|
+
# <b>A context block can exist next to normal <tt>def test_the_old_way; end</tt> tests</b>,
|
55
|
+
# meaning you do not have to fully commit to the context/should syntax in a test file.
|
56
|
+
#
|
57
|
+
|
58
|
+
module Context
|
59
|
+
def Context.included(other) # :nodoc:
|
60
|
+
@@context_names = []
|
61
|
+
@@setup_blocks = []
|
62
|
+
@@teardown_blocks = []
|
63
|
+
end
|
64
|
+
|
65
|
+
# Defines a test method. Can be called either inside our outside of a context.
|
66
|
+
# Optionally specify <tt>:unimplimented => true</tt> (see should_eventually).
|
67
|
+
#
|
68
|
+
# Example:
|
69
|
+
#
|
70
|
+
# class UserTest << Test::Unit::TestCase
|
71
|
+
# should "return first user on find(:first)"
|
72
|
+
# assert_equal users(:first), User.find(:first)
|
73
|
+
# end
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
# Would create a test named
|
77
|
+
# 'test: should return first user on find(:first)'
|
78
|
+
#
|
79
|
+
def should(name, opts = {}, &should_block)
|
80
|
+
test_name = ["test:", @@context_names, "should", "#{name}. "].flatten.join(' ').to_sym
|
81
|
+
|
82
|
+
name_defined = eval("self.instance_methods.include?('#{test_name.to_s.gsub(/['"]/, '\$1')}')", should_block.binding)
|
83
|
+
raise ArgumentError, "'#{test_name}' is already defined" and return if name_defined
|
84
|
+
|
85
|
+
setup_blocks = @@setup_blocks.dup
|
86
|
+
teardown_blocks = @@teardown_blocks.dup
|
87
|
+
|
88
|
+
if opts[:unimplemented]
|
89
|
+
define_method test_name do |*args|
|
90
|
+
# XXX find a better way of doing this.
|
91
|
+
assert true
|
92
|
+
STDOUT.putc "X" # Tests for this model are missing.
|
93
|
+
end
|
94
|
+
else
|
95
|
+
define_method test_name do |*args|
|
96
|
+
begin
|
97
|
+
setup_blocks.each {|b| b.bind(self).call }
|
98
|
+
should_block.bind(self).call(*args)
|
99
|
+
ensure
|
100
|
+
teardown_blocks.reverse.each {|b| b.bind(self).call }
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Creates a context block with the given name.
|
107
|
+
def context(name, &context_block)
|
108
|
+
saved_setups = @@setup_blocks.dup
|
109
|
+
saved_teardowns = @@teardown_blocks.dup
|
110
|
+
saved_contexts = @@context_names.dup
|
111
|
+
|
112
|
+
@@context_names << name
|
113
|
+
context_block.bind(self).call
|
114
|
+
|
115
|
+
@@context_names = saved_contexts
|
116
|
+
@@setup_blocks = saved_setups
|
117
|
+
@@teardown_blocks = saved_teardowns
|
118
|
+
end
|
119
|
+
|
120
|
+
# Run before every should block in the current context.
|
121
|
+
# If a setup block appears in a nested context, it will be run after the setup blocks
|
122
|
+
# in the parent contexts.
|
123
|
+
def setup(&setup_block)
|
124
|
+
@@setup_blocks << setup_block
|
125
|
+
end
|
126
|
+
|
127
|
+
# Run after every should block in the current context.
|
128
|
+
# If a teardown block appears in a nested context, it will be run before the teardown
|
129
|
+
# blocks in the parent contexts.
|
130
|
+
def teardown(&teardown_block)
|
131
|
+
@@teardown_blocks << teardown_block
|
132
|
+
end
|
133
|
+
|
134
|
+
# Defines a specification that is not yet implemented.
|
135
|
+
# Will be displayed as an 'X' when running tests, and failures will not be shown.
|
136
|
+
# This is equivalent to:
|
137
|
+
# should(name, {:unimplemented => true}, &block)
|
138
|
+
def should_eventually(name, &block)
|
139
|
+
should("eventually #{name}", {:unimplemented => true}, &block)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module ThoughtBot # :nodoc:
|
2
|
+
module Shoulda # :nodoc:
|
3
|
+
module General
|
4
|
+
def self.included(other) # :nodoc:
|
5
|
+
other.class_eval do
|
6
|
+
extend ThoughtBot::Shoulda::General::ClassMethods
|
7
|
+
# include ThoughtBot::Shoulda::General::InstanceMethods
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
# Loads all fixture files (<tt>test/fixtures/*.yml</tt>)
|
13
|
+
def load_all_fixtures
|
14
|
+
all_fixtures = Dir.glob(File.join(Test::Unit::TestCase.fixture_path, "*.yml")).collect do |f|
|
15
|
+
File.basename(f, '.yml').to_sym
|
16
|
+
end
|
17
|
+
fixtures *all_fixtures
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Prints a message to stdout, tagged with the name of the calling method.
|
22
|
+
def report!(msg = "")
|
23
|
+
puts("#{caller.first}: #{msg}")
|
24
|
+
end
|
25
|
+
|
26
|
+
# Ensures that the number of items in the collection changes
|
27
|
+
#
|
28
|
+
# assert_difference(User, :count, 1) { User.create }
|
29
|
+
# assert_difference(User.packages, :size, 3, true) { User.add_three_packages }
|
30
|
+
#
|
31
|
+
# Setting reload to true will call <tt>object.reload</tt> after the block (for ActiveRecord associations)
|
32
|
+
def assert_difference(object, method, difference, reload = false, msg = nil)
|
33
|
+
initial_value = object.send(method)
|
34
|
+
yield
|
35
|
+
object.send(:reload) if reload
|
36
|
+
assert_equal initial_value + difference, object.send(method), (msg || "#{object}##{method} after block")
|
37
|
+
end
|
38
|
+
|
39
|
+
# Ensures that object.method does not change. See assert_difference for usage.
|
40
|
+
def assert_no_difference(object, method, reload = false, msg = nil, &block)
|
41
|
+
assert_difference(object, method, 0, reload, msg, &block)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Asserts that two arrays contain the same elements, the same number of times. Essentially ==, but unordered.
|
45
|
+
#
|
46
|
+
# assert_same_elements([:a, :b, :c], [:c, :a, :b]) => passes
|
47
|
+
def assert_same_elements(a1, a2, msg = nil)
|
48
|
+
[:select, :inject, :size].each do |m|
|
49
|
+
[a1, a2].each {|a| assert_respond_to(a, m, "Are you sure that #{a.inspect} is an array? It doesn't respond to #{m}.") }
|
50
|
+
end
|
51
|
+
|
52
|
+
assert a1h = a1.inject({}) { |h,e| h[e] = a1.select { |i| i == e }.size; h }
|
53
|
+
assert a2h = a2.inject({}) { |h,e| h[e] = a2.select { |i| i == e }.size; h }
|
54
|
+
|
55
|
+
assert_equal(a1h, a2h, msg)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Asserts that the given collection contains item x. If x is a regular expression, ensure that
|
59
|
+
# at least one element from the collection matches x. +extra_msg+ is appended to the error message if the assertion fails.
|
60
|
+
#
|
61
|
+
# assert_contains(['a', '1'], /\d/) => passes
|
62
|
+
# assert_contains(['a', '1'], 'a') => passes
|
63
|
+
# assert_contains(['a', '1'], /not there/) => fails
|
64
|
+
def assert_contains(collection, x, extra_msg = "")
|
65
|
+
collection = [collection] unless collection.is_a?(Array)
|
66
|
+
msg = "#{x.inspect} not found in #{collection.to_a.inspect} " + extra_msg
|
67
|
+
case x
|
68
|
+
when Regexp: assert(collection.detect { |e| e =~ x }, msg)
|
69
|
+
else assert(collection.include?(x), msg)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Asserts that the given collection does not contain item x. If x is a regular expression, ensure that
|
74
|
+
# none of the elements from the collection match x.
|
75
|
+
def assert_does_not_contain(collection, x, extra_msg = "")
|
76
|
+
collection = [collection] unless collection.is_a?(Array)
|
77
|
+
msg = "#{x.inspect} found in #{collection.to_a.inspect} " + extra_msg
|
78
|
+
case x
|
79
|
+
when Regexp: assert(!collection.detect { |e| e =~ x }, msg)
|
80
|
+
else assert(!collection.include?(x), msg)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Asserts that the given object can be saved
|
85
|
+
#
|
86
|
+
# assert_save User.new(params)
|
87
|
+
def assert_save(obj)
|
88
|
+
assert obj.save, "Errors: #{obj.errors.full_messages.join('; ')}"
|
89
|
+
obj.reload
|
90
|
+
end
|
91
|
+
|
92
|
+
# Asserts that the given object is valid
|
93
|
+
#
|
94
|
+
# assert_save User.new(params)
|
95
|
+
def assert_valid(obj)
|
96
|
+
assert obj.valid?, "Errors: #{obj.errors.full_messages.join('; ')}"
|
97
|
+
end
|
98
|
+
|
99
|
+
# Asserts that the block uses ActionMailer to send emails
|
100
|
+
#
|
101
|
+
# assert_sends_email(2) { Mailer.deliver_messages }
|
102
|
+
def assert_sends_email(num = 1, &blk)
|
103
|
+
ActionMailer::Base.deliveries.clear
|
104
|
+
blk.call
|
105
|
+
msg = "Sent #{ActionMailer::Base.deliveries.size} emails, when #{num} expected:\n"
|
106
|
+
ActionMailer::Base.deliveries.each { |m| msg << " '#{m.subject}' sent to #{m.to.to_sentence}\n" }
|
107
|
+
assert(num == ActionMailer::Base.deliveries.size, msg)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Asserts that the block does not send emails thorough ActionMailer
|
111
|
+
#
|
112
|
+
# assert_does_not_send_email { # do nothing }
|
113
|
+
def assert_does_not_send_email(&blk)
|
114
|
+
assert_sends_email 0, &blk
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ThoughtBot # :nodoc:
|
2
|
+
module Shoulda # :nodoc:
|
3
|
+
module Private # :nodoc:
|
4
|
+
def get_options!(args, *wanted)
|
5
|
+
ret = []
|
6
|
+
opts = (args.last.is_a?(Hash) ? args.pop : {})
|
7
|
+
wanted.each {|w| ret << opts.delete(w)}
|
8
|
+
raise ArgumentError, "Unsuported options given: #{opts.keys.join(', ')}" unless opts.keys.empty?
|
9
|
+
return *ret
|
10
|
+
end
|
11
|
+
|
12
|
+
def model_class
|
13
|
+
self.name.gsub(/Test$/, '').constantize
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/uninstall.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Uninstall hook code here
|
metadata
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: giraffesoft-attribute_fu
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.2"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James Golick
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-08-04 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Creating multi-model forms is amazingly easy with AttributeFu.
|
17
|
+
email: james@giraffesoft.ca
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- init.rb
|
26
|
+
- lib
|
27
|
+
- lib/attribute_fu
|
28
|
+
- lib/attribute_fu/associated_form_helper.rb
|
29
|
+
- lib/attribute_fu/associations.rb
|
30
|
+
- lib/attribute_fu.rb
|
31
|
+
- MIT-LICENSE
|
32
|
+
- Rakefile
|
33
|
+
- README
|
34
|
+
- tasks
|
35
|
+
- tasks/attribute_fu_tasks.rake
|
36
|
+
- test
|
37
|
+
- test/app
|
38
|
+
- test/app/controllers
|
39
|
+
- test/app/controllers/application.rb
|
40
|
+
- test/app/helpers
|
41
|
+
- test/app/helpers/application_helper.rb
|
42
|
+
- test/app/models
|
43
|
+
- test/app/models/comment.rb
|
44
|
+
- test/app/models/photo.rb
|
45
|
+
- test/config
|
46
|
+
- test/config/boot.rb
|
47
|
+
- test/config/database.yml
|
48
|
+
- test/config/environment.rb
|
49
|
+
- test/config/environments
|
50
|
+
- test/config/environments/development.rb
|
51
|
+
- test/config/environments/test.rb
|
52
|
+
- test/config/routes.rb
|
53
|
+
- test/db
|
54
|
+
- test/db/migrate
|
55
|
+
- test/db/migrate/001_create_photos.rb
|
56
|
+
- test/db/migrate/002_create_comments.rb
|
57
|
+
- test/db/schema.rb
|
58
|
+
- test/Rakefile
|
59
|
+
- test/script
|
60
|
+
- test/script/console
|
61
|
+
- test/script/destroy
|
62
|
+
- test/script/generate
|
63
|
+
- test/script/server
|
64
|
+
- test/test
|
65
|
+
- test/test/test_helper.rb
|
66
|
+
- test/test/unit
|
67
|
+
- test/test/unit/associated_form_helper_test.rb
|
68
|
+
- test/test/unit/comment_test.rb
|
69
|
+
- test/test/unit/photo_test.rb
|
70
|
+
- test/vendor
|
71
|
+
- test/vendor/plugins
|
72
|
+
- test/vendor/plugins/shoulda
|
73
|
+
- test/vendor/plugins/shoulda/init.rb
|
74
|
+
- test/vendor/plugins/shoulda/lib
|
75
|
+
- test/vendor/plugins/shoulda/lib/shoulda
|
76
|
+
- test/vendor/plugins/shoulda/lib/shoulda/active_record_helpers.rb
|
77
|
+
- test/vendor/plugins/shoulda/lib/shoulda/context.rb
|
78
|
+
- test/vendor/plugins/shoulda/lib/shoulda/general.rb
|
79
|
+
- test/vendor/plugins/shoulda/lib/shoulda/private_helpers.rb
|
80
|
+
- test/vendor/plugins/shoulda/lib/shoulda.rb
|
81
|
+
- uninstall.rb
|
82
|
+
has_rdoc: true
|
83
|
+
homepage: http://jamesgolick.com/attribute_fu
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options:
|
86
|
+
- --main
|
87
|
+
- README
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: "0"
|
95
|
+
version:
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: "0"
|
101
|
+
version:
|
102
|
+
requirements: []
|
103
|
+
|
104
|
+
rubyforge_project:
|
105
|
+
rubygems_version: 1.2.0
|
106
|
+
signing_key:
|
107
|
+
specification_version: 2
|
108
|
+
summary: rails multi-model forms made easy!
|
109
|
+
test_files: []
|
110
|
+
|