with_model 0.3.2 → 1.0.0
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.
- checksums.yaml +4 -4
- data/.gitignore +5 -4
- data/.travis.yml +6 -16
- data/CHANGELOG.md +70 -0
- data/Gemfile +5 -6
- data/LICENSE +1 -1
- data/README.md +164 -0
- data/Rakefile +5 -13
- data/lib/with_model.rb +14 -15
- data/lib/with_model/constant_stubber.rb +24 -0
- data/lib/with_model/methods.rb +7 -0
- data/lib/with_model/model.rb +76 -0
- data/lib/with_model/model/dsl.rb +18 -0
- data/lib/with_model/table.rb +21 -0
- data/lib/with_model/version.rb +1 -1
- data/spec/active_record_behaviors_spec.rb +21 -19
- data/spec/readme_spec.rb +82 -63
- data/spec/spec_helper.rb +36 -31
- data/spec/with_model_spec.rb +136 -107
- data/with_model.gemspec +25 -19
- metadata +47 -16
- data/.autotest +0 -5
- data/CHANGELOG +0 -62
- data/README.rdoc +0 -122
- data/lib/with_model/base.rb +0 -10
- data/lib/with_model/dsl.rb +0 -53
@@ -0,0 +1,18 @@
|
|
1
|
+
module WithModel
|
2
|
+
class Model
|
3
|
+
class DSL
|
4
|
+
def initialize model
|
5
|
+
@model = model
|
6
|
+
end
|
7
|
+
|
8
|
+
def table options = {}, &block
|
9
|
+
@model.table_options = options
|
10
|
+
@model.table_block = block
|
11
|
+
end
|
12
|
+
|
13
|
+
def model &block
|
14
|
+
@model.model_block = block
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
module WithModel
|
4
|
+
class Table
|
5
|
+
def initialize name, options = {}, &block
|
6
|
+
@name = name.freeze
|
7
|
+
@options = options.freeze
|
8
|
+
@block = block
|
9
|
+
end
|
10
|
+
|
11
|
+
def create
|
12
|
+
connection = ActiveRecord::Base.connection
|
13
|
+
connection.drop_table(@name) if connection.table_exists?(@name)
|
14
|
+
connection.create_table(@name, @options, &@block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def destroy
|
18
|
+
ActiveRecord::Base.connection.drop_table(@name)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/with_model/version.rb
CHANGED
@@ -4,9 +4,11 @@ describe "ActiveRecord behaviors" do
|
|
4
4
|
describe "a temporary ActiveRecord model created with with_model" do
|
5
5
|
context "that has a named scope" do
|
6
6
|
before do
|
7
|
-
|
7
|
+
regular_model = Class.new ActiveRecord::Base do
|
8
8
|
scope :title_is_foo, lambda { where(:title => 'foo') }
|
9
9
|
end
|
10
|
+
stub_const 'RegularModel', regular_model
|
11
|
+
|
10
12
|
RegularModel.connection.drop_table(RegularModel.table_name) rescue nil
|
11
13
|
RegularModel.connection.create_table(RegularModel.table_name) do |t|
|
12
14
|
t.string 'title'
|
@@ -32,25 +34,26 @@ describe "ActiveRecord behaviors" do
|
|
32
34
|
end
|
33
35
|
|
34
36
|
describe "the named scope" do
|
35
|
-
it "
|
36
|
-
included = RegularModel.create!(:title => 'foo', :content =>
|
37
|
-
excluded = RegularModel.create!(:title => 'bar', :content =>
|
37
|
+
it "works like a regular named scope" do
|
38
|
+
included = RegularModel.create!(:title => 'foo', :content => 'Include me!')
|
39
|
+
excluded = RegularModel.create!(:title => 'bar', :content => 'Include me!')
|
38
40
|
|
39
|
-
RegularModel.title_is_foo.
|
41
|
+
expect(RegularModel.title_is_foo).to eq [included]
|
40
42
|
|
41
|
-
included = BlogPost.create!(:title => 'foo', :content =>
|
42
|
-
excluded = BlogPost.create!(:title => 'bar', :content =>
|
43
|
+
included = BlogPost.create!(:title => 'foo', :content => 'Include me!')
|
44
|
+
excluded = BlogPost.create!(:title => 'bar', :content => 'Include me!')
|
43
45
|
|
44
|
-
BlogPost.title_is_foo.
|
46
|
+
expect(BlogPost.title_is_foo).to eq [included]
|
45
47
|
end
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
49
51
|
context "that has a polymorphic belongs_to" do
|
50
52
|
before do
|
51
|
-
|
53
|
+
animal = Class.new ActiveRecord::Base do
|
52
54
|
has_many :tea_cups, :as => :pet
|
53
55
|
end
|
56
|
+
stub_const 'Animal', animal
|
54
57
|
end
|
55
58
|
|
56
59
|
with_model :TeaCup do
|
@@ -71,17 +74,17 @@ describe "ActiveRecord behaviors" do
|
|
71
74
|
end
|
72
75
|
|
73
76
|
describe "the polymorphic belongs_to" do
|
74
|
-
it "
|
77
|
+
it "works like a regular polymorphic belongs_to" do
|
75
78
|
animal = Animal.create!
|
76
79
|
stuffed_animal = StuffedAnimal.create!
|
77
80
|
|
78
81
|
tea_cup_for_animal = TeaCup.create!(:pet => animal)
|
79
|
-
tea_cup_for_animal.pet_type.
|
80
|
-
animal.tea_cups.
|
82
|
+
expect(tea_cup_for_animal.pet_type).to eq 'Animal'
|
83
|
+
expect(animal.tea_cups).to include(tea_cup_for_animal)
|
81
84
|
|
82
85
|
tea_cup_for_stuffed_animal = TeaCup.create!(:pet => stuffed_animal)
|
83
|
-
tea_cup_for_stuffed_animal.pet_type.
|
84
|
-
stuffed_animal.tea_cups.
|
86
|
+
expect(tea_cup_for_stuffed_animal.pet_type).to eq 'StuffedAnimal'
|
87
|
+
expect(stuffed_animal.tea_cups).to include(tea_cup_for_stuffed_animal)
|
85
88
|
end
|
86
89
|
end
|
87
90
|
end
|
@@ -97,18 +100,17 @@ describe "ActiveRecord behaviors" do
|
|
97
100
|
end
|
98
101
|
end
|
99
102
|
|
100
|
-
with_model :Country
|
101
|
-
end
|
103
|
+
with_model :Country
|
102
104
|
|
103
105
|
context "in earlier examples" do
|
104
|
-
it "
|
106
|
+
it "works as normal" do
|
105
107
|
Province.create!(:country => Country.create!)
|
106
108
|
end
|
107
109
|
end
|
108
110
|
|
109
111
|
context "in later examples" do
|
110
|
-
it "
|
111
|
-
Province.reflect_on_association(:country).klass.
|
112
|
+
it "does not hold a reference to earlier example groups' classes" do
|
113
|
+
expect(Province.reflect_on_association(:country).klass).to eq Country
|
112
114
|
end
|
113
115
|
end
|
114
116
|
end
|
data/spec/readme_spec.rb
CHANGED
@@ -1,86 +1,105 @@
|
|
1
|
-
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
table do |t|
|
8
|
-
t.string :title
|
9
|
-
t.timestamps
|
10
|
-
end
|
11
|
-
|
12
|
-
# The model block works just like the class definition.
|
13
|
-
model do
|
14
|
-
include SomeModule
|
15
|
-
has_many :comments
|
16
|
-
validates_presence_of :title
|
3
|
+
describe "A blog post" do
|
4
|
+
before :all do
|
5
|
+
module SomeModule; end
|
6
|
+
end
|
17
7
|
|
18
|
-
|
19
|
-
|
20
|
-
|
8
|
+
after :all do
|
9
|
+
Object.send :remove_const, :SomeModule
|
10
|
+
end
|
21
11
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
12
|
+
with_model :BlogPost do
|
13
|
+
# The table block works just like a migration.
|
14
|
+
table do |t|
|
15
|
+
t.string :title
|
16
|
+
t.timestamps
|
26
17
|
end
|
27
18
|
|
28
|
-
#
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
19
|
+
# The model block works just like the class definition.
|
20
|
+
model do
|
21
|
+
include SomeModule
|
22
|
+
has_many :comments
|
23
|
+
validates_presence_of :title
|
24
|
+
|
25
|
+
def self.some_class_method
|
26
|
+
'chunky'
|
34
27
|
end
|
35
28
|
|
36
|
-
|
37
|
-
|
29
|
+
def some_instance_method
|
30
|
+
'bacon'
|
38
31
|
end
|
39
32
|
end
|
33
|
+
end
|
40
34
|
|
41
|
-
|
42
|
-
|
35
|
+
# with_model classes can have associations.
|
36
|
+
with_model :Comment do
|
37
|
+
table do |t|
|
38
|
+
t.string :text
|
39
|
+
t.belongs_to :blog_post
|
40
|
+
t.timestamps
|
43
41
|
end
|
44
42
|
|
45
|
-
|
46
|
-
|
43
|
+
model do
|
44
|
+
belongs_to :blog_post
|
47
45
|
end
|
46
|
+
end
|
48
47
|
|
49
|
-
|
50
|
-
|
51
|
-
|
48
|
+
it "can be accessed as a constant" do
|
49
|
+
expect(BlogPost).to be
|
50
|
+
end
|
52
51
|
|
53
|
-
|
54
|
-
|
55
|
-
|
52
|
+
it "has the module" do
|
53
|
+
expect(BlogPost.include?(SomeModule)).to be_true
|
54
|
+
end
|
56
55
|
|
57
|
-
|
58
|
-
|
59
|
-
record.should_not be_valid
|
60
|
-
record.title = "foo"
|
61
|
-
record.should be_valid
|
62
|
-
record.save.should be_true
|
63
|
-
record.reload.should == record
|
64
|
-
record.comments.create!(:text => "Lorem ipsum")
|
65
|
-
record.comments.count.should == 1
|
66
|
-
end
|
56
|
+
it "has the class method" do
|
57
|
+
expect(BlogPost.some_class_method).to eq 'chunky'
|
67
58
|
end
|
68
59
|
|
69
|
-
|
70
|
-
|
71
|
-
defined?(BlogPost).should be_false
|
72
|
-
end
|
60
|
+
it "has the instance method" do
|
61
|
+
expect(BlogPost.new.some_instance_method).to eq 'bacon'
|
73
62
|
end
|
74
63
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
64
|
+
it "can do all the things a regular model can" do
|
65
|
+
record = BlogPost.new
|
66
|
+
expect(record).to_not be_valid
|
67
|
+
record.title = "foo"
|
68
|
+
expect(record).to be_valid
|
69
|
+
expect(record.save).to be_true
|
70
|
+
expect(record.reload).to eq record
|
71
|
+
record.comments.create!(:text => "Lorem ipsum")
|
72
|
+
expect(record.comments.count).to eq 1
|
73
|
+
end
|
74
|
+
|
75
|
+
# with_model classes can have inheritance.
|
76
|
+
class Car < ActiveRecord::Base
|
77
|
+
self.abstract_class = true
|
78
|
+
end
|
79
|
+
|
80
|
+
with_model :Ford, superclass: Car do
|
81
|
+
end
|
82
|
+
|
83
|
+
it "has a specified superclass" do
|
84
|
+
expect(Ford < Car).to be_true
|
85
|
+
end
|
86
|
+
end
|
82
87
|
|
83
|
-
|
84
|
-
|
88
|
+
describe "another example group" do
|
89
|
+
it "does not have the constant anymore" do
|
90
|
+
expect(defined?(BlogPost)).to be_false
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "with table options" do
|
95
|
+
with_model :WithOptions do
|
96
|
+
table :id => false do |t|
|
97
|
+
t.string 'foo'
|
98
|
+
t.timestamps
|
85
99
|
end
|
86
100
|
end
|
101
|
+
|
102
|
+
it "respects the additional options" do
|
103
|
+
expect(WithOptions.columns.map(&:name)).to_not include("id")
|
104
|
+
end
|
105
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
|
1
|
+
require 'bundler'
|
2
|
+
Bundler.setup
|
3
3
|
|
4
4
|
begin
|
5
5
|
require 'coveralls'
|
@@ -7,43 +7,48 @@ begin
|
|
7
7
|
rescue LoadError
|
8
8
|
end
|
9
9
|
|
10
|
+
require 'with_model'
|
10
11
|
RSpec.configure do |config|
|
11
12
|
config.extend WithModel
|
13
|
+
|
14
|
+
config.warnings = true
|
15
|
+
|
16
|
+
config.expect_with :rspec do |c|
|
17
|
+
c.syntax = :expect
|
18
|
+
end
|
19
|
+
|
20
|
+
config.mock_with :rspec do |c|
|
21
|
+
c.syntax = :expect
|
22
|
+
end
|
12
23
|
end
|
13
24
|
|
14
|
-
|
15
|
-
adapter =
|
25
|
+
is_jruby = RUBY_PLATFORM =~ /\bjava\b/
|
26
|
+
adapter = is_jruby ? 'jdbcsqlite3' : 'sqlite3'
|
16
27
|
|
17
28
|
# WithModel requires ActiveRecord::Base.connection to be established.
|
18
29
|
# If ActiveRecord already has a connection, as in a Rails app, this is unnecessary.
|
19
|
-
|
20
|
-
|
21
|
-
# For readme_spec.rb
|
22
|
-
module SomeModule; end
|
23
|
-
|
24
|
-
if defined?(ActiveModel)
|
25
|
-
shared_examples_for "ActiveModel" do
|
26
|
-
require 'test/unit/assertions'
|
27
|
-
require 'active_model/lint'
|
28
|
-
include Test::Unit::Assertions
|
29
|
-
include ActiveModel::Lint::Tests
|
30
|
-
|
31
|
-
# to_s is to support ruby-1.9
|
32
|
-
ActiveModel::Lint::Tests.public_instance_methods.map{|m| m.to_s}.grep(/^test/).each do |m|
|
33
|
-
example m.gsub('_',' ') do
|
34
|
-
begin
|
35
|
-
send m
|
36
|
-
rescue
|
37
|
-
puts $!.message
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
30
|
+
require 'active_record'
|
31
|
+
ActiveRecord::Base.establish_connection(:adapter => adapter, :database => ':memory:')
|
41
32
|
|
42
|
-
|
43
|
-
|
33
|
+
if defined?(I18n) && I18n.respond_to?(:enforce_available_locales=)
|
34
|
+
I18n.enforce_available_locales = true
|
35
|
+
end
|
36
|
+
|
37
|
+
if ENV['LOGGER']
|
38
|
+
require 'logger'
|
39
|
+
ActiveRecord::Base.logger = Logger.new($stdout)
|
44
40
|
end
|
45
41
|
|
46
|
-
|
47
|
-
|
48
|
-
|
42
|
+
module SpecHelper
|
43
|
+
module RailsTestCompatability
|
44
|
+
if ::ActiveRecord::VERSION::STRING >= '4.1.0'
|
45
|
+
require 'minitest'
|
46
|
+
include Minitest::Assertions
|
47
|
+
def assertions; @assertions || 0; end
|
48
|
+
def assertions= value; @assertions = value; end
|
49
|
+
else
|
50
|
+
require 'test/unit/assertions'
|
51
|
+
include Test::Unit::Assertions
|
52
|
+
end
|
53
|
+
end
|
49
54
|
end
|
data/spec/with_model_spec.rb
CHANGED
@@ -1,5 +1,24 @@
|
|
1
|
+
require 'active_model'
|
1
2
|
require 'spec_helper'
|
2
3
|
|
4
|
+
shared_examples_for "ActiveModel" do
|
5
|
+
require 'active_model/lint'
|
6
|
+
include SpecHelper::RailsTestCompatability
|
7
|
+
include ActiveModel::Lint::Tests
|
8
|
+
|
9
|
+
active_model_methods = ActiveModel::Lint::Tests.public_instance_methods
|
10
|
+
active_model_lint_tests = active_model_methods.map(&:to_s).grep(/^test/)
|
11
|
+
|
12
|
+
active_model_lint_tests.each do |method_name|
|
13
|
+
friendly_name = method_name.gsub('_', ' ')
|
14
|
+
example friendly_name do
|
15
|
+
public_send method_name.to_sym
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
before { @model = subject }
|
20
|
+
end
|
21
|
+
|
3
22
|
describe "a temporary ActiveRecord model created with with_model" do
|
4
23
|
non_shadowing_example_ran = false
|
5
24
|
|
@@ -22,52 +41,48 @@ describe "a temporary ActiveRecord model created with with_model" do
|
|
22
41
|
non_shadowing_example_ran = true
|
23
42
|
end
|
24
43
|
|
25
|
-
it "
|
26
|
-
record = BlogPost.create!(:title => 'New blog post', :content =>
|
44
|
+
it "acts like a normal ActiveRecord model" do
|
45
|
+
record = BlogPost.create!(:title => 'New blog post', :content => 'Hello, world!')
|
27
46
|
|
28
47
|
record.reload
|
29
48
|
|
30
|
-
record.title.
|
31
|
-
record.content.
|
32
|
-
record.updated_at.
|
49
|
+
expect(record.title).to eq 'New blog post'
|
50
|
+
expect(record.content).to eq 'Hello, world!'
|
51
|
+
expect(record.updated_at).to be_present
|
33
52
|
|
34
53
|
record.destroy
|
35
54
|
|
36
|
-
|
37
|
-
record.reload
|
38
|
-
}.should raise_error(ActiveRecord::RecordNotFound)
|
55
|
+
expect { record.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
39
56
|
end
|
40
57
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
it_should_behave_like "ActiveModel"
|
45
|
-
end
|
58
|
+
describe "the class" do
|
59
|
+
subject { BlogPost.new }
|
60
|
+
it_should_behave_like "ActiveModel"
|
46
61
|
end
|
47
62
|
|
48
|
-
it "
|
49
|
-
BlogPost.new(:title => 'New blog post').fancy_title.
|
63
|
+
it "has the methods defined in its model block" do
|
64
|
+
expect(BlogPost.new(:title => 'New blog post').fancy_title).to eq 'Title: New blog post'
|
50
65
|
end
|
51
66
|
|
52
|
-
it "
|
53
|
-
BlogPost.
|
67
|
+
it "defines a constant" do
|
68
|
+
expect(BlogPost).to be_a(Class)
|
54
69
|
end
|
55
70
|
|
56
71
|
describe ".with_model?" do
|
57
|
-
it "
|
58
|
-
BlogPost.with_model
|
72
|
+
it "returns true" do
|
73
|
+
expect(BlogPost.with_model?).to be_true
|
59
74
|
end
|
60
75
|
end
|
61
76
|
|
62
|
-
it "
|
63
|
-
BlogPost.base_class.
|
77
|
+
it "is its own base_class" do
|
78
|
+
expect(BlogPost.base_class).to eq BlogPost
|
64
79
|
end
|
65
80
|
end
|
66
81
|
|
67
82
|
context "after an example which uses with_model without shadowing an existing constant" do
|
68
|
-
it "
|
69
|
-
non_shadowing_example_ran.
|
70
|
-
defined?(BlogPost).
|
83
|
+
it "returns the constant to its undefined state" do
|
84
|
+
expect(non_shadowing_example_ran).to be_true
|
85
|
+
expect(defined?(BlogPost)).to be_false
|
71
86
|
end
|
72
87
|
end
|
73
88
|
|
@@ -82,49 +97,59 @@ describe "a temporary ActiveRecord model created with with_model" do
|
|
82
97
|
shadowing_example_ran = true
|
83
98
|
end
|
84
99
|
|
85
|
-
it "
|
86
|
-
MyConst.
|
100
|
+
it "shadows that constant" do
|
101
|
+
expect(MyConst).to be_a(Class)
|
87
102
|
end
|
88
103
|
end
|
89
104
|
|
90
105
|
context "in later examples" do
|
91
|
-
it "
|
92
|
-
shadowing_example_ran.
|
93
|
-
MyConst.
|
106
|
+
it "returns the constant to its original value" do
|
107
|
+
expect(shadowing_example_ran).to be_true
|
108
|
+
expect(MyConst).to eq 1
|
94
109
|
end
|
95
110
|
end
|
96
111
|
|
97
112
|
describe "with a plural name" do
|
98
113
|
with_model :BlogPosts
|
99
114
|
|
100
|
-
it "
|
101
|
-
BlogPosts.
|
102
|
-
lambda { BlogPost }.
|
115
|
+
it "does not singularize the constant name" do
|
116
|
+
expect(BlogPosts).to be
|
117
|
+
expect(lambda { BlogPost }).to raise_error(NameError)
|
103
118
|
end
|
104
119
|
end
|
105
120
|
|
106
121
|
describe "with a name containing capital letters" do
|
107
122
|
with_model :BlogPost
|
108
123
|
|
109
|
-
it "
|
110
|
-
BlogPost.table_name.
|
111
|
-
BlogPost.table_name.
|
124
|
+
it "tableizes the table name" do
|
125
|
+
expect(BlogPost.table_name).to match(/_blog_posts_/)
|
126
|
+
expect(BlogPost.table_name).to eq BlogPost.table_name.downcase
|
112
127
|
end
|
113
128
|
end
|
114
129
|
|
115
130
|
describe "with a name with underscores" do
|
116
131
|
with_model :blog_post
|
117
132
|
|
118
|
-
it "
|
119
|
-
BlogPost.
|
133
|
+
it "constantizes the name" do
|
134
|
+
expect(BlogPost).to be
|
120
135
|
end
|
121
136
|
|
122
|
-
it "
|
123
|
-
BlogPost.table_name.
|
124
|
-
BlogPost.table_name.
|
137
|
+
it "tableizes the table name" do
|
138
|
+
expect(BlogPost.table_name).to match(/_blog_posts_/)
|
139
|
+
expect(BlogPost.table_name).to eq BlogPost.table_name.downcase
|
125
140
|
end
|
126
141
|
end
|
127
142
|
|
143
|
+
describe "using the constant in the model block" do
|
144
|
+
with_model :BlogPost do
|
145
|
+
model do
|
146
|
+
raise 'I am not myself!' unless self == BlogPost
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
it "is available" do end
|
151
|
+
end
|
152
|
+
|
128
153
|
module AMixin
|
129
154
|
def foo
|
130
155
|
end
|
@@ -139,9 +164,9 @@ describe "a temporary ActiveRecord model created with with_model" do
|
|
139
164
|
|
140
165
|
before { ::ModelWithMixin = WithAMixin }
|
141
166
|
|
142
|
-
it "
|
143
|
-
lambda { ::ModelWithMixin.new.foo }.
|
144
|
-
::ModelWithMixin.include?(AMixin).
|
167
|
+
it "has the mixin" do
|
168
|
+
expect(lambda { ::ModelWithMixin.new.foo }).to_not raise_error
|
169
|
+
expect(::ModelWithMixin.include?(AMixin)).to be_true
|
145
170
|
end
|
146
171
|
end
|
147
172
|
|
@@ -163,26 +188,17 @@ describe "a temporary ActiveRecord model created with with_model" do
|
|
163
188
|
end
|
164
189
|
end
|
165
190
|
|
166
|
-
it "
|
167
|
-
subject.
|
191
|
+
it "only has one after_save callback" do
|
192
|
+
expect(subject).to receive(:my_method).once
|
168
193
|
subject.save
|
169
194
|
end
|
170
195
|
|
171
|
-
it "
|
172
|
-
subject.
|
196
|
+
it "still only has one after_save callback in future tests" do
|
197
|
+
expect(subject).to receive(:my_method).once
|
173
198
|
subject.save
|
174
199
|
end
|
175
200
|
end
|
176
201
|
|
177
|
-
if defined?(Mixico)
|
178
|
-
context "after a context that uses a mixin" do
|
179
|
-
it "should not have the mixin" do
|
180
|
-
lambda { ::ModelWithMixin.new.foo }.should raise_error(NoMethodError)
|
181
|
-
::ModelWithMixin.include?(AMixin).should be_false
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
202
|
context "with table options" do
|
187
203
|
with_model :WithOptions do
|
188
204
|
table :id => false do |t|
|
@@ -191,48 +207,40 @@ describe "a temporary ActiveRecord model created with with_model" do
|
|
191
207
|
end
|
192
208
|
end
|
193
209
|
|
194
|
-
it "
|
195
|
-
WithOptions.columns.map(&:name).
|
210
|
+
it "respects the additional options" do
|
211
|
+
expect(WithOptions.columns.map(&:name)).to_not include('id')
|
196
212
|
end
|
197
213
|
end
|
198
214
|
|
199
215
|
context "without a block" do
|
200
216
|
with_model :BlogPost
|
201
217
|
|
202
|
-
it "
|
218
|
+
it "acts like a normal ActiveRecord model" do
|
203
219
|
record = BlogPost.create!
|
204
220
|
record.reload
|
205
221
|
record.destroy
|
206
|
-
|
207
|
-
record.reload
|
208
|
-
}.should raise_error(ActiveRecord::RecordNotFound)
|
222
|
+
expect { record.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
209
223
|
end
|
210
224
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
it_should_behave_like "ActiveModel"
|
215
|
-
end
|
225
|
+
describe "the class" do
|
226
|
+
subject { BlogPost.new }
|
227
|
+
it_should_behave_like "ActiveModel"
|
216
228
|
end
|
217
229
|
end
|
218
230
|
|
219
231
|
context "with an empty block" do
|
220
232
|
with_model(:BlogPost) {}
|
221
233
|
|
222
|
-
it "
|
234
|
+
it "acts like a normal ActiveRecord model" do
|
223
235
|
record = BlogPost.create!
|
224
236
|
record.reload
|
225
237
|
record.destroy
|
226
|
-
|
227
|
-
record.reload
|
228
|
-
}.should raise_error(ActiveRecord::RecordNotFound)
|
238
|
+
expect { record.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
229
239
|
end
|
230
240
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
it_should_behave_like "ActiveModel"
|
235
|
-
end
|
241
|
+
describe "the class" do
|
242
|
+
subject { BlogPost.new }
|
243
|
+
it_should_behave_like "ActiveModel"
|
236
244
|
end
|
237
245
|
end
|
238
246
|
|
@@ -245,50 +253,40 @@ describe "a temporary ActiveRecord model created with with_model" do
|
|
245
253
|
end
|
246
254
|
end
|
247
255
|
|
248
|
-
it "
|
249
|
-
record = BlogPost.create!(:title => 'New blog post', :content =>
|
256
|
+
it "acts like a normal ActiveRecord model" do
|
257
|
+
record = BlogPost.create!(:title => 'New blog post', :content => 'Hello, world!')
|
250
258
|
|
251
259
|
record.reload
|
252
260
|
|
253
|
-
record.title.
|
254
|
-
record.content.
|
255
|
-
record.updated_at.
|
261
|
+
expect(record.title).to eq 'New blog post'
|
262
|
+
expect(record.content).to eq 'Hello, world!'
|
263
|
+
expect(record.updated_at).to be_present
|
256
264
|
|
257
265
|
record.destroy
|
258
266
|
|
259
|
-
|
260
|
-
record.reload
|
261
|
-
}.should raise_error(ActiveRecord::RecordNotFound)
|
267
|
+
expect { record.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
262
268
|
end
|
263
269
|
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
it_should_behave_like "ActiveModel"
|
268
|
-
end
|
270
|
+
describe "the class" do
|
271
|
+
subject { BlogPost.new }
|
272
|
+
it_should_behave_like "ActiveModel"
|
269
273
|
end
|
270
|
-
|
271
274
|
end
|
272
275
|
|
273
|
-
context "without a table block" do
|
274
|
-
with_model :BlogPost
|
275
|
-
end
|
276
|
+
context "without a table or model block" do
|
277
|
+
with_model :BlogPost
|
276
278
|
|
277
|
-
it "
|
278
|
-
BlogPost.columns.map(&:name).
|
279
|
+
it "acts like a normal ActiveRecord model" do
|
280
|
+
expect(BlogPost.columns.map(&:name)).to eq ['id']
|
279
281
|
record = BlogPost.create!
|
280
282
|
record.reload
|
281
283
|
record.destroy
|
282
|
-
|
283
|
-
record.reload
|
284
|
-
}.should raise_error(ActiveRecord::RecordNotFound)
|
284
|
+
expect { record.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
285
285
|
end
|
286
286
|
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
it_should_behave_like "ActiveModel"
|
291
|
-
end
|
287
|
+
describe "the class" do
|
288
|
+
subject { BlogPost.new }
|
289
|
+
it_should_behave_like "ActiveModel"
|
292
290
|
end
|
293
291
|
end
|
294
292
|
|
@@ -296,15 +294,46 @@ describe "a temporary ActiveRecord model created with with_model" do
|
|
296
294
|
with_model :BlogPost
|
297
295
|
|
298
296
|
it "includes the correct model class in descendants on the first test run" do
|
299
|
-
ActiveRecord::Base.descendants.detect do |c|
|
297
|
+
descendant = ActiveRecord::Base.descendants.detect do |c|
|
300
298
|
c.table_name == BlogPost.table_name
|
301
|
-
end
|
299
|
+
end
|
300
|
+
expect(descendant).to eq BlogPost
|
302
301
|
end
|
303
302
|
|
304
303
|
it "includes the correct model class in descendants on the second test run" do
|
305
|
-
ActiveRecord::Base.descendants.detect do |c|
|
304
|
+
descendant = ActiveRecord::Base.descendants.detect do |c|
|
306
305
|
c.table_name == BlogPost.table_name
|
307
|
-
end
|
306
|
+
end
|
307
|
+
expect(descendant).to eq BlogPost
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
context "with 'superclass' option" do
|
312
|
+
class BlogPostParent < ActiveRecord::Base
|
313
|
+
self.abstract_class = true
|
314
|
+
end
|
315
|
+
|
316
|
+
with_model :BlogPost, superclass: BlogPostParent do
|
317
|
+
table do |t|
|
318
|
+
t.string 'title'
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
describe "the class" do
|
323
|
+
subject { BlogPost.new }
|
324
|
+
it_should_behave_like "ActiveModel"
|
325
|
+
end
|
326
|
+
|
327
|
+
it "is a subclass of the supplied superclass" do
|
328
|
+
expect(BlogPost < BlogPostParent).to be_true
|
329
|
+
end
|
330
|
+
|
331
|
+
it "is its own base_class" do
|
332
|
+
expect(BlogPost.base_class).to eq BlogPost
|
333
|
+
end
|
334
|
+
|
335
|
+
it "responds to .with_model? with true" do
|
336
|
+
expect(BlogPost.with_model?).to be_true
|
308
337
|
end
|
309
338
|
end
|
310
339
|
end
|