fixture_replacement 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/CHANGELOG.rdoc +720 -0
- data/GPL_LICENSE +674 -0
- data/MIT_LICENSE +22 -0
- data/README.rdoc +154 -0
- data/Rakefile +8 -0
- data/TODO.rdoc +22 -0
- data/VERSION +1 -0
- data/contributions.rdoc +48 -0
- data/etc/bug_reports/2007_09_28_linoj.txt +51 -0
- data/etc/google_analytics +6 -0
- data/etc/patches/2007_09_14_default_model_name_with_arguments.diff +26 -0
- data/etc/patches/2007_10_14_active_record_specs.diff +396 -0
- data/etc/patches/2007_10_14_protected_attributes.diff +26 -0
- data/etc/patches/2007_10_14_send_patch.diff +79 -0
- data/etc/patches/2007_10_14_spelling_error_in_comments.diff +13 -0
- data/etc/patches/2007_10_17_protected_attributes_second_go.diff +212 -0
- data/etc/patches/2007_10_18_README.diff +137 -0
- data/etc/patches/2007_10_19_readme_tweak.diff +12 -0
- data/etc/patches/2007_10_19_silence_migration.diff +12 -0
- data/etc/patches/2007_10_25_changed_classify_to_camelize.diff +38 -0
- data/etc/patches/2007_11_20_fixture_replacement_generator_should_not_reload_environment_or_boot.patch +13 -0
- data/etc/patches/2007_11_20_string_random_refactor_and_extension.patch +104 -0
- data/etc/patches/2007_11_20_string_random_refactor_and_extension_v2.patch +108 -0
- data/fixture_replacement.gemspec +126 -0
- data/lib/fixture_replacement.rb +16 -0
- data/lib/fixture_replacement/attribute_builder.rb +129 -0
- data/lib/fixture_replacement/class_methods.rb +45 -0
- data/lib/fixture_replacement/method_generator.rb +38 -0
- data/lib/fixture_replacement/version.rb +13 -0
- data/lib/fr.rb +1 -0
- data/philosophy_and_bugs.rdoc +128 -0
- data/rake_tasks/code_quality.rb +37 -0
- data/rake_tasks/docs.rb +59 -0
- data/rake_tasks/gem.rb +27 -0
- data/rake_tasks/specs.rb +7 -0
- data/rake_tasks/tests.rb +7 -0
- data/rake_tasks/website.rb +11 -0
- data/spec/fixture_replacement/attribute_builder_spec.rb +162 -0
- data/spec/fixture_replacement/fixture_replacement_spec.rb +96 -0
- data/spec/fixture_replacement/fixtures/classes.rb +78 -0
- data/spec/fixture_replacement/fr_spec.rb +7 -0
- data/spec/fixture_replacement/integration/attr_protected_attributes_spec.rb +71 -0
- data/spec/fixture_replacement/integration/attributes_for_with_invalid_keys_spec.rb +14 -0
- data/spec/fixture_replacement/integration/attributes_from_spec_without_block.rb +52 -0
- data/spec/fixture_replacement/integration/create_method_spec.rb +61 -0
- data/spec/fixture_replacement/integration/cyclic_dependency_spec.rb +32 -0
- data/spec/fixture_replacement/integration/default_warnings_spec.rb +29 -0
- data/spec/fixture_replacement/integration/extend_spec.rb +37 -0
- data/spec/fixture_replacement/integration/has_and_belongs_to_many_spec.rb +64 -0
- data/spec/fixture_replacement/integration/new_method_spec.rb +96 -0
- data/spec/fixture_replacement/integration/private_methods_spec.rb +43 -0
- data/spec/fixture_replacement/integration/public_methods_spec.rb +21 -0
- data/spec/fixture_replacement/integration/valid_attributes_spec.rb +41 -0
- data/spec/fixture_replacement/integration/validation_spec.rb +54 -0
- data/spec/fixture_replacement/regressions/2008_01_21_random_string_with_sti_spec.rb +71 -0
- data/spec/fixture_replacement/version_spec.rb +7 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/spec_helpers.rb +117 -0
- data/test/test_helper.rb +21 -0
- data/test/unit/user_test.rb +57 -0
- metadata +143 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
module FixtureReplacement
|
2
|
+
module ClassMethods
|
3
|
+
def attributes_for(fixture_name, options={}, &block)
|
4
|
+
builder = AttributeBuilder.new(fixture_name, options, &block)
|
5
|
+
MethodGenerator.new(builder, self).generate_methods
|
6
|
+
end
|
7
|
+
|
8
|
+
def validate!
|
9
|
+
AttributeBuilder.validate_instances!
|
10
|
+
end
|
11
|
+
|
12
|
+
def random_string(length=10)
|
13
|
+
chars = ("a".."z").to_a
|
14
|
+
string = ""
|
15
|
+
1.upto(length) { |i| string << chars[rand(chars.size-1)]}
|
16
|
+
string
|
17
|
+
end
|
18
|
+
|
19
|
+
def load_example_data
|
20
|
+
load "#{rails_root}/db/example_data.rb"
|
21
|
+
rescue LoadError
|
22
|
+
# no-op. If the file is not found, don't panic
|
23
|
+
end
|
24
|
+
|
25
|
+
def rails_root
|
26
|
+
defined?(RAILS_ROOT) ? RAILS_ROOT : "."
|
27
|
+
end
|
28
|
+
|
29
|
+
def reload!
|
30
|
+
AttributeBuilder.clear_out_instances!
|
31
|
+
load File.expand_path(File.dirname(__FILE__) + "/../fixture_replacement.rb")
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# Any user defined instance methods need the module's class scope to be
|
37
|
+
# accessible inside the block given to attributes_for
|
38
|
+
#
|
39
|
+
# Addresses bug #16858 (see CHANGELOG)
|
40
|
+
def method_added(method)
|
41
|
+
module_function method if method != :method_added
|
42
|
+
public method
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module FixtureReplacement
|
2
|
+
class MethodGenerator
|
3
|
+
def initialize(builder, evaluation_module)
|
4
|
+
@builder = builder
|
5
|
+
@evaluation_module = evaluation_module
|
6
|
+
end
|
7
|
+
|
8
|
+
def generate_methods
|
9
|
+
builder = @builder
|
10
|
+
builder_name = builder.fixture_name
|
11
|
+
|
12
|
+
@evaluation_module.module_eval do
|
13
|
+
define_method("valid_#{builder_name}_attributes") do |*args|
|
14
|
+
obj = __send__ "new_#{builder_name}"
|
15
|
+
obj.attributes
|
16
|
+
end
|
17
|
+
|
18
|
+
define_method("create_#{builder_name}") do |*args|
|
19
|
+
obj = __send__("new_#{builder_name}", *args)
|
20
|
+
obj.save!
|
21
|
+
obj
|
22
|
+
end
|
23
|
+
|
24
|
+
define_method("new_#{builder_name}") do |*args|
|
25
|
+
new_object = builder.instantiate(*args)
|
26
|
+
end
|
27
|
+
|
28
|
+
define_method("default_#{builder_name}") do |*args|
|
29
|
+
warning = "default_#{builder_name} has been deprecated. "
|
30
|
+
warning << "Please replace instances of default_#{builder_name} with the new_#{builder_name} method"
|
31
|
+
Kernel.warn(warning)
|
32
|
+
|
33
|
+
__send__ "new_#{builder_name}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module FixtureReplacement
|
2
|
+
module Version
|
3
|
+
unless defined?(FixtureReplacement::VERSION)
|
4
|
+
MAJOR = 3
|
5
|
+
MINOR = 0
|
6
|
+
TINY = 1
|
7
|
+
|
8
|
+
version_string = "#{MAJOR}.#{MINOR}.#{TINY}"
|
9
|
+
version_string << " RC#{RELEASE_CANDIDATE}" if defined?(RELEASE_CANDIDATE)
|
10
|
+
VERSION = version_string
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/fr.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
FR = FixtureReplacement unless defined?(FR)
|
@@ -0,0 +1,128 @@
|
|
1
|
+
== Motivation Behind FixtureReplacement
|
2
|
+
|
3
|
+
As Dan Manges has outlined in his blog post, "Fixing Fixtures with Factory" (http://www.dcmanges.com/blog/38),
|
4
|
+
this approach to generating test data has a number of advantages:
|
5
|
+
|
6
|
+
- The factory provides default values and relationships
|
7
|
+
- Invalid data will never be loaded into your test database, as it is with the typical YAML fixture.
|
8
|
+
A record which is created with a create_* method (create_user, create_post, etc.) uses ActiveRecord's
|
9
|
+
create! behind the scenes, so any invalid data will raise a clear error. This means that you will
|
10
|
+
spend your time debugging your tests and code, not your test data.
|
11
|
+
- It's in Ruby, so you won't have to fight with YAML's spacing issues, plus the data is by nature
|
12
|
+
more dynamic and more agile.
|
13
|
+
- When a test fails (and they will), someone who hasn't written the test will be able to figure out
|
14
|
+
the *intention* behind the test. They won't have to go digging through YAML files to figure out
|
15
|
+
the relevant data to the test.
|
16
|
+
- No more opening of 5 different YAML files to see the associations and column names of different models -
|
17
|
+
this is conveniently located in one file (db/example_data.rb)
|
18
|
+
- If you set use_transactional_fixtures = true in your test_helper or spec_helper (and you *really* should
|
19
|
+
be using this), the data that is created in each test will be rolled back, meaning no-side effects,
|
20
|
+
and a consistent database among different developers, and for your self during different test runs.
|
21
|
+
|
22
|
+
=== Random Data in db/example_data.rb
|
23
|
+
|
24
|
+
The use of random data should also be spoken of. Many may think this to be dangerous, but in fact random
|
25
|
+
data is often helpful. Consider the following snippets of psudo-code (along with it's test):
|
26
|
+
|
27
|
+
# apps/models/user.rb :
|
28
|
+
# ----------------------
|
29
|
+
|
30
|
+
class User < ActiveRecord::Base
|
31
|
+
validates_uniqueness_of :username
|
32
|
+
validates_presence_of :password
|
33
|
+
|
34
|
+
after_create :check_password
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def check_password
|
39
|
+
# ...
|
40
|
+
end
|
41
|
+
|
42
|
+
public
|
43
|
+
|
44
|
+
def establish_friendship_with(other_user)
|
45
|
+
# ...
|
46
|
+
end
|
47
|
+
|
48
|
+
def friends
|
49
|
+
# ...
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# The test:
|
54
|
+
# ---------
|
55
|
+
|
56
|
+
def test_make_sure_user_can_establish_friendship
|
57
|
+
@user_one = User.create({
|
58
|
+
:username => "foo",
|
59
|
+
:password => "some password",
|
60
|
+
:password_confirmation => "some password_confirmation"
|
61
|
+
})
|
62
|
+
|
63
|
+
@user_two = User.create({
|
64
|
+
:username => "bar",
|
65
|
+
:password => "some password",
|
66
|
+
:password_confirmation => "some password confirmation"
|
67
|
+
})
|
68
|
+
|
69
|
+
@user_one.establish_friendship_with(@user_two)
|
70
|
+
@user_one.friends.should == [@user_two]
|
71
|
+
end
|
72
|
+
|
73
|
+
Notice that the above test adds a lot of extra noise in getting valid users into the database; The test, however, doesn't care what the usernames are, that the password is a good one, that the password matches the password confirmation, and so on. The point of the test is not to check those things, but rather that a friendship can be established.
|
74
|
+
|
75
|
+
Here would be a similar test with the FixtureReplacement:
|
76
|
+
|
77
|
+
# The test:
|
78
|
+
# ---------
|
79
|
+
|
80
|
+
before do
|
81
|
+
@user_one = create_user
|
82
|
+
@user_two = create_user
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_make_sure_user_can_establish_friendship
|
86
|
+
@user_one.establish_friendship_with(@user_two)
|
87
|
+
@user_one.friends.should == [@user_two]
|
88
|
+
end
|
89
|
+
|
90
|
+
Once again, the test above doesn't care about usernames, so why should you? But to even store those two users into the database, you will need unique usernames, as well as password which match. Here is where the random data comes in:
|
91
|
+
|
92
|
+
# db/example_data.rb
|
93
|
+
# -------------------
|
94
|
+
|
95
|
+
module FixtureReplacement
|
96
|
+
attributes_for :user do |u|
|
97
|
+
password = random_string
|
98
|
+
|
99
|
+
u.username = random_string
|
100
|
+
u.password = password
|
101
|
+
u.password_confirmation = password
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
Now, in a different test case, if you do care about the usernames not being random, it is easy to set them:
|
106
|
+
|
107
|
+
create_user({
|
108
|
+
:username => "scott",
|
109
|
+
:password => "foobar",
|
110
|
+
:password_confirmation => "foobar"
|
111
|
+
})
|
112
|
+
|
113
|
+
=== Disadvantages of FixtureReplacement
|
114
|
+
|
115
|
+
The one major disadvantage behind this approach is that it's slow - just as slow as fixtures, if not slower.
|
116
|
+
One approach that the rspec crowd is using is to use this plugin in integration tests, while using mocks & stubs
|
117
|
+
in model unit tests. It's not a big deal if your integration tests run slow, since you probably don't run
|
118
|
+
them very often.
|
119
|
+
|
120
|
+
Another approach is to look to external sources to speed up your test suite:
|
121
|
+
|
122
|
+
- a sqlite3 in-memory database (can cut your test/spec time in half)
|
123
|
+
- unit-record gem (by Dan Manges), which takes advantage of multi-core processors
|
124
|
+
- a distributed build system, such as spec_distributed
|
125
|
+
- running tests individually, or per file
|
126
|
+
- A faster machine
|
127
|
+
|
128
|
+
If you have other ideas for speeding up your test suite, I'm all ears.
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec/rake/spectask'
|
2
|
+
require 'spec/rake/verify_rcov'
|
3
|
+
|
4
|
+
desc "Run all examples with RCov"
|
5
|
+
Spec::Rake::SpecTask.new(:rcov) do |t|
|
6
|
+
t.rcov = true
|
7
|
+
t.rcov_opts = ['--exclude', 'spec', '--exclude', 'gems']
|
8
|
+
t.rcov_dir = "doc/rcov"
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "Feel the pain of my code, and submit a refactoring patch"
|
12
|
+
task :flog do
|
13
|
+
puts %x(find lib | grep ".rb$" | xargs flog)
|
14
|
+
end
|
15
|
+
|
16
|
+
task :flog_to_disk => :create_doc_directory do
|
17
|
+
puts "Flogging..."
|
18
|
+
%x(find lib | grep ".rb$" | xargs flog > doc/flog.txt)
|
19
|
+
puts "Done Flogging...\n"
|
20
|
+
end
|
21
|
+
|
22
|
+
def sloc
|
23
|
+
`sloccount #{File.dirname(__FILE__)}/lib`
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "Output sloccount report. You'll need sloccount installed."
|
27
|
+
task :sloc do
|
28
|
+
puts "Counting lines of code"
|
29
|
+
puts sloc
|
30
|
+
end
|
31
|
+
|
32
|
+
desc "Write sloccount report"
|
33
|
+
task :output_sloc => :create_doc_directory do
|
34
|
+
File.open(File.dirname(__FILE__) + "/doc/lines_of_code.txt", "w") do |f|
|
35
|
+
f << sloc
|
36
|
+
end
|
37
|
+
end
|
data/rake_tasks/docs.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'hanna/rdoctask'
|
2
|
+
|
3
|
+
def doc_directory
|
4
|
+
"doc"
|
5
|
+
end
|
6
|
+
|
7
|
+
desc 'Generate documentation for the fixture_replacement plugin.'
|
8
|
+
Rake::RDocTask.new(:rdoc_without_analytics) do |rdoc|
|
9
|
+
rdoc.rdoc_dir = doc_directory
|
10
|
+
rdoc.title = 'FixtureReplacement'
|
11
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
12
|
+
|
13
|
+
rdoc.options << '--webcvs=http://github.com/smtlaissezfaire/fixturereplacement/tree/master/'
|
14
|
+
|
15
|
+
[
|
16
|
+
"README.rdoc",
|
17
|
+
"CHANGELOG.rdoc",
|
18
|
+
"GPL_LICENSE",
|
19
|
+
"MIT_LICENSE",
|
20
|
+
"contributions.rdoc",
|
21
|
+
"philosophy_and_bugs.rdoc",
|
22
|
+
"lib/**/*.rb"
|
23
|
+
].each do |file|
|
24
|
+
rdoc.rdoc_files.include(file)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
task :rdoc => [:rdoc_without_analytics] do
|
29
|
+
google_analytics = File.read(File.dirname(__FILE__) + "/etc/google_analytics")
|
30
|
+
rdoc_index = File.dirname(__FILE__) + "/#{doc_directory}/index.html"
|
31
|
+
|
32
|
+
contents = File.read(rdoc_index)
|
33
|
+
contents.gsub!("</head>", "#{google_analytics}\n</head>")
|
34
|
+
|
35
|
+
File.open(rdoc_index, "r+") do |file|
|
36
|
+
file.write(contents)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
task :rerdoc => [:clobber_rdoc, :rdoc]
|
41
|
+
task :clobber_rdoc => [:clobber_rdoc_without_analytics]
|
42
|
+
|
43
|
+
def create_doc_directory
|
44
|
+
unless File.exists?(doc_directory)
|
45
|
+
`mkdir doc`
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
task :create_doc_directory do
|
50
|
+
create_doc_directory
|
51
|
+
end
|
52
|
+
|
53
|
+
desc "Create the html specdoc"
|
54
|
+
Spec::Rake::SpecTask.new(:specdoc => :create_doc_directory) do |t|
|
55
|
+
t.spec_opts = ["--format", "html:doc/specdoc.html"]
|
56
|
+
end
|
57
|
+
|
58
|
+
desc 'Create the specdoc + rdoc'
|
59
|
+
task :build_docs => [:rerdoc, :specdoc, :rcov, :flog_to_disk]
|
data/rake_tasks/gem.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../lib/fixture_replacement")
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'jeweler'
|
5
|
+
|
6
|
+
Jeweler::Tasks.new do |gemspec|
|
7
|
+
File.open(File.expand_path(File.dirname(__FILE__) + "/../VERSION"), "w") do |f|
|
8
|
+
f << FixtureReplacement::Version::VERSION
|
9
|
+
end
|
10
|
+
|
11
|
+
gemspec.name = "fixture_replacement"
|
12
|
+
gemspec.summary = "The original fixture replacement solution for rails"
|
13
|
+
gemspec.email = "scott@railsnewbie.com"
|
14
|
+
gemspec.homepage = "http://replacefixtures.rubyforge.org"
|
15
|
+
gemspec.authors = ["Scott Taylor"]
|
16
|
+
gemspec.description = <<-DESC
|
17
|
+
FixtureReplacement is a Rails plugin that provides a simple way to
|
18
|
+
quickly populate your test database with model objects without having to manage multiple,
|
19
|
+
brittle fixture files. You can easily set up complex object graphs (with models which
|
20
|
+
reference other models) and add new objects on the fly.
|
21
|
+
DESC
|
22
|
+
end
|
23
|
+
|
24
|
+
Jeweler::GemcutterTasks.new
|
25
|
+
rescue LoadError
|
26
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
27
|
+
end
|
data/rake_tasks/specs.rb
ADDED
data/rake_tasks/tests.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'rake/contrib/rubyforgepublisher'
|
2
|
+
|
3
|
+
desc 'Publish the website, building the docs first'
|
4
|
+
task :publish_website => [:build_docs] do
|
5
|
+
publisher = Rake::SshDirPublisher.new(
|
6
|
+
"smtlaissezfaire@rubyforge.org",
|
7
|
+
"/var/www/gforge-projects/replacefixtures/",
|
8
|
+
"doc"
|
9
|
+
)
|
10
|
+
publisher.upload
|
11
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../spec_helper"
|
2
|
+
|
3
|
+
module FixtureReplacement
|
4
|
+
describe AttributeBuilder do
|
5
|
+
before do
|
6
|
+
AttributeBuilder.clear_out_instances!
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should add the instance to the global attributes" do
|
10
|
+
a = AttributeBuilder.new(:foo)
|
11
|
+
AttributeBuilder.instances.should == [a]
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should have no instances when none have been created" do
|
15
|
+
AttributeBuilder.instances.should == []
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should have two instances when two have been created" do
|
19
|
+
a1 = AttributeBuilder.new(:foo)
|
20
|
+
a2 = AttributeBuilder.new(:foo)
|
21
|
+
AttributeBuilder.instances.should == [a1, a2]
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should have the fixture name as accessible" do
|
25
|
+
a1 = AttributeBuilder.new(:foo)
|
26
|
+
a1.fixture_name.should == :foo
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should have the from attribute as nil, if none provided" do
|
30
|
+
a1 = AttributeBuilder.new(:foo)
|
31
|
+
a1.from.should be_nil
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should have the from attribute as the symbol of the attribute from which it derives" do
|
35
|
+
a1 = AttributeBuilder.new(:foo, :from => :bar)
|
36
|
+
a1.from.should == :bar
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should be able to find the Attribute by fixture name" do
|
40
|
+
a = AttributeBuilder.new(:baz)
|
41
|
+
AttributeBuilder.find_by_fixture_name(:baz).should == a
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should find no attributes for fixture_name :baz, if it was never created" do
|
45
|
+
a = AttributeBuilder.new(:bar)
|
46
|
+
AttributeBuilder.find_by_fixture_name(:baz).should be_nil
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should find no attributes for fixture_name :baz, if no fixture at all was ever created" do
|
50
|
+
AttributeBuilder.find_by_fixture_name(:baz).should be_nil
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should have the class name if specified" do
|
54
|
+
AttributeBuilder.new(:foo, :class => Object).active_record_class.should == Object
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should use the class name of the fixture_name, camel-cased, if the class is unspecified, and the fixture uninherited" do
|
58
|
+
AttributeBuilder.new(:object).active_record_class.should == Object
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should use the class name of the inherited attribute, if specified" do
|
62
|
+
AttributeBuilder.new(:foo, :class => Object)
|
63
|
+
AttributeBuilder.new(:bar, :from => :foo).active_record_class.should == Bar
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should prefer the constantized name to the derived name" do
|
67
|
+
AttributeBuilder.new(:user)
|
68
|
+
AttributeBuilder.new(:admin, :from => :user).active_record_class.should == Admin
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should use the derived name if the constantized name fails (doesn't exist)" do
|
72
|
+
AttributeBuilder.new(:foo)
|
73
|
+
no_constant = AttributeBuilder.new(:no_constant, :from => :foo)
|
74
|
+
no_constant.active_record_class.should == Foo
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should raise a name error if it has no class, the name can't be constantized, and is derived, but the derived class can't be constantized" do
|
78
|
+
builder_one = AttributeBuilder.new(:does_not_exist)
|
79
|
+
builder_two = AttributeBuilder.new(:also_does_not_exist, :from => :does_not_exist)
|
80
|
+
|
81
|
+
lambda {
|
82
|
+
builder_two.active_record_class
|
83
|
+
}.should raise_error(NameError)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should not raise an error if the model ends with 's'" do
|
87
|
+
AttributeBuilder.new(:actress).active_record_class.should == Actress
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should allow a string key" do
|
91
|
+
AttributeBuilder.new(:admin, "from" => :user).active_record_class.should == Admin
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should allow a string name for the builder" do
|
95
|
+
AttributeBuilder.new("admin").active_record_class.should == Admin
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should store the from key as a symbol, even when passed a string" do
|
99
|
+
builder = AttributeBuilder.new(:admin, "from" => "user")
|
100
|
+
builder.from.should == :user
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should convert the fixture name to a symbol" do
|
104
|
+
builder = AttributeBuilder.new("admin")
|
105
|
+
builder.fixture_name.should == :admin
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "validating all instances" do
|
109
|
+
it "should return true if there are no instances" do
|
110
|
+
AttributeBuilder.validate_instances!.should be_true
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should raise an error if an instance is not valid" do
|
114
|
+
AttributeBuilder.new(:validate_name)
|
115
|
+
|
116
|
+
lambda {
|
117
|
+
AttributeBuilder.validate_instances!
|
118
|
+
}.should raise_error
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should not raise an error if there is only one instance, and it is valid" do
|
122
|
+
AttributeBuilder.new(:event)
|
123
|
+
|
124
|
+
lambda {
|
125
|
+
AttributeBuilder.validate_instances!
|
126
|
+
}.should_not raise_error
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should raise an error, giving the fixture name, and the error" do
|
130
|
+
AttributeBuilder.new(:validate_name)
|
131
|
+
|
132
|
+
lambda {
|
133
|
+
AttributeBuilder.validate_instances!
|
134
|
+
}.should raise_error(FixtureReplacement::InvalidInstance, "new_validate_name is not valid! - Errors: [name: can't be blank]")
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should use the correct name" do
|
138
|
+
AttributeBuilder.new(:validate_name_two)
|
139
|
+
|
140
|
+
lambda {
|
141
|
+
AttributeBuilder.validate_instances!
|
142
|
+
}.should raise_error(FixtureReplacement::InvalidInstance, "new_validate_name_two is not valid! - Errors: [name: can't be blank]")
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should use the correct errors" do
|
146
|
+
AttributeBuilder.new(:address_with_valid_city)
|
147
|
+
|
148
|
+
lambda {
|
149
|
+
AttributeBuilder.validate_instances!
|
150
|
+
}.should raise_error(FixtureReplacement::InvalidInstance, "new_address_with_valid_city is not valid! - Errors: [city: can't be blank]")
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should use multiple errors on a single model" do
|
154
|
+
AttributeBuilder.new(:address_with_valid_city_and_state)
|
155
|
+
|
156
|
+
lambda {
|
157
|
+
AttributeBuilder.validate_instances!
|
158
|
+
}.should raise_error(FixtureReplacement::InvalidInstance, "new_address_with_valid_city_and_state is not valid! - Errors: [city: can't be blank], [state: can't be blank]")
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|