with_model 2.0.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rubocop.yml +6 -0
- data/.travis.yml +22 -16
- data/Gemfile +11 -6
- data/LICENSE +1 -1
- data/README.md +11 -15
- data/Rakefile +20 -0
- data/bin/rake +18 -0
- data/lib/with_model.rb +4 -8
- data/lib/with_model/constant_stubber.rb +30 -8
- data/lib/with_model/methods.rb +2 -0
- data/lib/with_model/model.rb +7 -15
- data/lib/with_model/model/dsl.rb +10 -3
- data/lib/with_model/table.rb +3 -1
- data/lib/with_model/version.rb +3 -1
- data/spec/active_record_behaviors_spec.rb +27 -25
- data/spec/readme_spec.rb +23 -25
- data/spec/spec_helper.rb +13 -16
- data/spec/with_model_spec.rb +80 -68
- data/with_model.gemspec +14 -14
- metadata +27 -17
- data/Rakefile.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 22f429a5cb8e986623de65004594810d642f7ca21b0bf24a0a1257defa40add9
|
4
|
+
data.tar.gz: a7a0cbbe47ba722b1359a438c18692a7927ff957c88cd0e0919ac3ab4ac65e92
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 63d816a1fe0782ee315073325b6eb59b468bc87c7899f3a124c181cc6542ee9c31d55768a3e2af8234ec6ffad9bb92037b012da5328128e835fce4a74d7a6b15
|
7
|
+
data.tar.gz: 6da66d3cbf860d19d5a2c661e01e75ff7aef341d78d64d12055d5c28ebc5e7401ea5c095b6b006da1c01bcb4b2100bf524681a63292ccf791cff7def6a987115
|
data/.rubocop.yml
ADDED
data/.travis.yml
CHANGED
@@ -2,36 +2,42 @@ language: ruby
|
|
2
2
|
sudo: false
|
3
3
|
|
4
4
|
rvm:
|
5
|
-
- "2.
|
6
|
-
- "2.
|
7
|
-
- "2.
|
8
|
-
- jruby-9.
|
5
|
+
- "2.5.1"
|
6
|
+
- "2.4.4"
|
7
|
+
- "2.3.7"
|
8
|
+
- jruby-9.2.0.0
|
9
9
|
|
10
10
|
install:
|
11
11
|
- bundle install --retry=3
|
12
12
|
|
13
13
|
env:
|
14
14
|
- ACTIVE_RECORD_BRANCH="master"
|
15
|
+
- ACTIVE_RECORD_BRANCH="5-2-stable"
|
16
|
+
- ACTIVE_RECORD_BRANCH="5-1-stable"
|
15
17
|
- ACTIVE_RECORD_BRANCH="5-0-stable"
|
16
|
-
-
|
18
|
+
- ACTIVE_RECORD_VERSION="~> 5.2.0"
|
19
|
+
- ACTIVE_RECORD_VERSION="~> 5.1.0"
|
17
20
|
- ACTIVE_RECORD_VERSION="~> 5.0.0"
|
18
21
|
- ACTIVE_RECORD_VERSION="~> 4.2.0"
|
19
22
|
|
20
23
|
matrix:
|
21
24
|
allow_failures:
|
22
25
|
- env: ACTIVE_RECORD_BRANCH="master"
|
26
|
+
- env: ACTIVE_RECORD_BRANCH="5-2-stable"
|
27
|
+
- env: ACTIVE_RECORD_BRANCH="5-1-stable"
|
23
28
|
- env: ACTIVE_RECORD_BRANCH="5-0-stable"
|
24
|
-
- env: ACTIVE_RECORD_BRANCH="4-2-stable"
|
25
29
|
exclude:
|
26
|
-
- rvm:
|
30
|
+
- rvm: 2.3.7
|
27
31
|
env: ACTIVE_RECORD_BRANCH="master"
|
28
|
-
- rvm:
|
29
|
-
env: ACTIVE_RECORD_BRANCH="5-0-stable"
|
30
|
-
- rvm: "2.1.10"
|
31
|
-
env: ACTIVE_RECORD_VERSION="~> 5.0.0"
|
32
|
-
- rvm: jruby-9.1.6.0
|
32
|
+
- rvm: jruby-9.2.0.0
|
33
33
|
env: ACTIVE_RECORD_BRANCH="master"
|
34
|
-
- rvm: jruby-9.
|
35
|
-
env: ACTIVE_RECORD_BRANCH="5-
|
36
|
-
- rvm: jruby-9.
|
37
|
-
env: ACTIVE_RECORD_VERSION="~> 5.
|
34
|
+
- rvm: jruby-9.2.0.0
|
35
|
+
env: ACTIVE_RECORD_BRANCH="5-2-stable"
|
36
|
+
- rvm: jruby-9.2.0.0
|
37
|
+
env: ACTIVE_RECORD_VERSION="~> 5.2.0"
|
38
|
+
- rvm: jruby-9.2.0.0
|
39
|
+
env: ACTIVE_RECORD_VERSION="~> 4.2.0"
|
40
|
+
|
41
|
+
addons:
|
42
|
+
code_climate:
|
43
|
+
repo_token: fe5c8a8b1b951a54707c08b6fb2a9a5edf9e0522d28bccc648454f774c9ccab1
|
data/Gemfile
CHANGED
@@ -1,12 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
source 'https://rubygems.org'
|
2
4
|
|
3
5
|
gemspec
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
gem 'lint-config-ruby', git: 'https://github.com/Casecommons/lint-config-ruby.git', tag: 'v1.0.0'
|
8
|
+
|
9
|
+
ar_branch = ENV['ACTIVE_RECORD_BRANCH']
|
10
|
+
ar_version = ENV['ACTIVE_RECORD_VERSION']
|
9
11
|
|
10
|
-
if
|
11
|
-
gem 'activerecord',
|
12
|
+
if ar_branch
|
13
|
+
gem 'activerecord', git: 'https://github.com/rails/rails.git', branch: ar_branch
|
14
|
+
gem 'arel', git: 'https://github.com/rails/arel.git' if ar_branch == 'master'
|
15
|
+
elsif ar_version
|
16
|
+
gem 'activerecord', ar_version # rubocop:disable Bundler/DuplicatedGem
|
12
17
|
end
|
data/LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2010-
|
1
|
+
Copyright (c) 2010-2018 Case Commons, Inc. <http://casecommons.org>
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
4
|
of this software and associated documentation files (the "Software"), to deal
|
data/README.md
CHANGED
@@ -2,11 +2,13 @@
|
|
2
2
|
|
3
3
|
[![Gem Version](https://img.shields.io/gem/v/with_model.svg?style=flat)](https://rubygems.org/gems/with_model)
|
4
4
|
[![Build Status](https://secure.travis-ci.org/Casecommons/with_model.svg?branch=master)](https://travis-ci.org/Casecommons/with_model)
|
5
|
-
[![Code Climate](https://img.shields.io/codeclimate/github/Casecommons/with_model.svg?style=flat)](https://codeclimate.com/github/Casecommons/with_model)
|
6
|
-
[![Coverage Status](https://img.shields.io/coveralls/Casecommons/with_model/master.svg?style=flat)](https://coveralls.io/r/Casecommons/with_model)
|
7
5
|
|
8
6
|
`with_model` dynamically builds an ActiveRecord model (with table) before each test in a group and destroys it afterwards.
|
9
7
|
|
8
|
+
## Development status
|
9
|
+
|
10
|
+
`with_model` is actively maintained. It is quite stable, so while updates may appear infrequent, it is only because none are needed.
|
11
|
+
|
10
12
|
## Installation
|
11
13
|
|
12
14
|
Install as usual: `gem install with_model` or add `gem 'with_model'` to your Gemfile. See `.travis.yml` for supported (tested) Ruby versions.
|
@@ -43,24 +45,18 @@ After setting up as above, call `with_model` and inside its block pass it a `tab
|
|
43
45
|
require 'spec_helper'
|
44
46
|
|
45
47
|
describe "A blog post" do
|
46
|
-
|
47
|
-
module SomeModule; end
|
48
|
-
end
|
49
|
-
|
50
|
-
after :all do
|
51
|
-
Object.send :remove_const, :SomeModule
|
52
|
-
end
|
48
|
+
module MyModule; end
|
53
49
|
|
54
50
|
with_model :BlogPost do
|
55
|
-
# The table block
|
51
|
+
# The table block (and an options hash) is passed to ActiveRecord migration’s `create_table`.
|
56
52
|
table do |t|
|
57
53
|
t.string :title
|
58
54
|
t.timestamps null: false
|
59
55
|
end
|
60
56
|
|
61
|
-
# The model block
|
57
|
+
# The model block is the ActiveRecord model’s class body.
|
62
58
|
model do
|
63
|
-
include
|
59
|
+
include MyModule
|
64
60
|
has_many :comments
|
65
61
|
validates_presence_of :title
|
66
62
|
|
@@ -92,7 +88,7 @@ describe "A blog post" do
|
|
92
88
|
end
|
93
89
|
|
94
90
|
it "has the module" do
|
95
|
-
expect(BlogPost.include?(
|
91
|
+
expect(BlogPost.include?(MyModule)).to eq true
|
96
92
|
end
|
97
93
|
|
98
94
|
it "has the class method" do
|
@@ -171,9 +167,9 @@ end
|
|
171
167
|
|
172
168
|
## Versioning
|
173
169
|
|
174
|
-
|
170
|
+
`with_model` uses [Semantic Versioning 2.0.0](http://semver.org/spec/v2.0.0.html).
|
175
171
|
|
176
172
|
## License
|
177
173
|
|
178
|
-
Copyright © 2010–
|
174
|
+
Copyright © 2010–2018 [Case Commons, Inc](http://casecommons.org).
|
179
175
|
Licensed under the MIT license, see [LICENSE](/LICENSE) file.
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
require 'rubocop/rake_task'
|
6
|
+
|
7
|
+
desc 'Run specs'
|
8
|
+
RSpec::Core::RakeTask.new
|
9
|
+
|
10
|
+
desc 'Run lint'
|
11
|
+
RuboCop::RakeTask.new
|
12
|
+
|
13
|
+
namespace 'doc' do
|
14
|
+
desc 'Generate README and preview in browser'
|
15
|
+
task 'readme' do
|
16
|
+
sh 'markdown README.md > README.html && open README.html'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
task default: %i[spec rubocop]
|
data/bin/rake
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rake' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'pathname'
|
12
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile',
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
require 'rubygems'
|
16
|
+
require 'bundler/setup'
|
17
|
+
|
18
|
+
load Gem.bin_path('rake', 'rake')
|
data/lib/with_model.rb
CHANGED
@@ -1,13 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'with_model/model'
|
2
4
|
require 'with_model/model/dsl'
|
3
5
|
require 'with_model/table'
|
4
6
|
require 'with_model/version'
|
5
7
|
|
6
8
|
module WithModel
|
7
|
-
def with_model(name,
|
8
|
-
options = options.dup
|
9
|
-
scope = options.delete(:scope)
|
10
|
-
|
9
|
+
def with_model(name, scope: nil, **options, &block)
|
11
10
|
model = Model.new name, options
|
12
11
|
dsl = Model::DSL.new model
|
13
12
|
dsl.instance_exec(&block) if block
|
@@ -21,10 +20,7 @@ module WithModel
|
|
21
20
|
end
|
22
21
|
end
|
23
22
|
|
24
|
-
def with_table(name,
|
25
|
-
options = options.dup
|
26
|
-
scope = options.delete(:scope)
|
27
|
-
|
23
|
+
def with_table(name, scope: nil, **options, &block)
|
28
24
|
table = Table.new name, options, &block
|
29
25
|
|
30
26
|
before(*scope) do
|
@@ -1,24 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module WithModel
|
2
4
|
class ConstantStubber
|
3
|
-
def initialize
|
5
|
+
def initialize(const_name)
|
4
6
|
@const_name = const_name.to_sym
|
7
|
+
@namespace = nil
|
5
8
|
@original_value = nil
|
6
9
|
end
|
7
10
|
|
8
|
-
def stub_const
|
9
|
-
|
10
|
-
|
11
|
-
|
11
|
+
def stub_const(value)
|
12
|
+
@namespace = namespace
|
13
|
+
if @namespace.const_defined?(basename)
|
14
|
+
@original_value = @namespace.const_get(basename)
|
15
|
+
@namespace.__send__ :remove_const, basename
|
12
16
|
end
|
13
17
|
|
14
|
-
|
18
|
+
@namespace.const_set basename, value
|
15
19
|
end
|
16
20
|
|
17
21
|
def unstub_const
|
18
|
-
|
19
|
-
|
22
|
+
@namespace.__send__ :remove_const, basename
|
23
|
+
@namespace.const_set basename, @original_value if @original_value
|
24
|
+
@namespace = nil
|
20
25
|
@original_value = nil
|
21
26
|
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def namespace
|
31
|
+
*namespace_parts, _ = lookup_list
|
32
|
+
namespace_parts.reduce(Object) do |ns, ns_part|
|
33
|
+
ns.const_get(ns_part.to_sym)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def lookup_list
|
38
|
+
@const_name.to_s.split('::')
|
39
|
+
end
|
40
|
+
|
41
|
+
def basename
|
42
|
+
@basename ||= lookup_list.last
|
43
|
+
end
|
22
44
|
end
|
23
45
|
private_constant :ConstantStubber
|
24
46
|
end
|
data/lib/with_model/methods.rb
CHANGED
data/lib/with_model/model.rb
CHANGED
@@ -1,23 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_record'
|
2
4
|
require 'active_support/core_ext/string/inflections'
|
5
|
+
require 'English'
|
3
6
|
require 'with_model/constant_stubber'
|
4
7
|
require 'with_model/methods'
|
5
8
|
require 'with_model/table'
|
6
9
|
|
7
10
|
module WithModel
|
8
11
|
class Model
|
9
|
-
OPTIONS = [:superclass].freeze
|
10
|
-
private_constant :OPTIONS
|
11
|
-
|
12
12
|
attr_writer :model_block, :table_block, :table_options
|
13
13
|
|
14
|
-
def initialize
|
15
|
-
validate_options!(options)
|
14
|
+
def initialize(name, superclass: ActiveRecord::Base)
|
16
15
|
@name = name.to_sym
|
17
16
|
@model_block = nil
|
18
17
|
@table_block = nil
|
19
18
|
@table_options = {}
|
20
|
-
@superclass =
|
19
|
+
@superclass = superclass
|
21
20
|
end
|
22
21
|
|
23
22
|
def create
|
@@ -68,15 +67,8 @@ module WithModel
|
|
68
67
|
end
|
69
68
|
|
70
69
|
def table_name
|
71
|
-
uid = "
|
72
|
-
"with_model_#{@name.to_s.tableize}_#{uid}"
|
73
|
-
end
|
74
|
-
|
75
|
-
def validate_options!(options)
|
76
|
-
unknown_options = options.keys - OPTIONS
|
77
|
-
unless unknown_options.empty?
|
78
|
-
raise ArgumentError, "unknown options: #{unknown_options.inspect}"
|
79
|
-
end
|
70
|
+
uid = "#{$PID}_#{Thread.current.object_id}"
|
71
|
+
"with_model_#{@name.to_s.tableize}_#{uid}"
|
80
72
|
end
|
81
73
|
end
|
82
74
|
end
|
data/lib/with_model/model/dsl.rb
CHANGED
@@ -1,16 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module WithModel
|
2
4
|
class Model
|
3
5
|
class DSL
|
4
|
-
def initialize
|
6
|
+
def initialize(model)
|
5
7
|
@model = model
|
6
8
|
end
|
7
9
|
|
8
|
-
|
10
|
+
# Provide a schema definition for the table, passed to ActiveRecord’s `create_table`.
|
11
|
+
# The table name will be auto-generated.
|
12
|
+
#
|
13
|
+
# @see https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-create_table
|
14
|
+
def table(options = {}, &block)
|
9
15
|
@model.table_options = options
|
10
16
|
@model.table_block = block
|
11
17
|
end
|
12
18
|
|
13
|
-
|
19
|
+
# Provide a class body for the ActiveRecord model.
|
20
|
+
def model(&block)
|
14
21
|
@model.model_block = block
|
15
22
|
end
|
16
23
|
end
|
data/lib/with_model/table.rb
CHANGED
data/lib/with_model/version.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
|
-
describe
|
4
|
-
describe
|
5
|
-
context
|
5
|
+
describe 'ActiveRecord behaviors' do
|
6
|
+
describe 'a temporary ActiveRecord model created with with_model' do
|
7
|
+
context 'that has a named scope' do
|
6
8
|
before do
|
7
9
|
@regular_model = Class.new ActiveRecord::Base do
|
8
|
-
scope :title_is_foo,
|
10
|
+
scope :title_is_foo, -> { where(title: 'foo') }
|
9
11
|
end
|
10
12
|
|
11
13
|
@regular_model.connection.create_table(@regular_model.table_name, force: true) do |t|
|
@@ -27,39 +29,39 @@ describe "ActiveRecord behaviors" do
|
|
27
29
|
end
|
28
30
|
|
29
31
|
model do
|
30
|
-
scope :title_is_foo,
|
32
|
+
scope :title_is_foo, -> { where(title: 'foo') }
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
34
|
-
describe
|
35
|
-
it
|
36
|
-
included = @regular_model.create!(:
|
37
|
-
|
36
|
+
describe 'the named scope' do
|
37
|
+
it 'works like a regular named scope' do
|
38
|
+
included = @regular_model.create!(title: 'foo', content: 'Include me!')
|
39
|
+
@regular_model.create!(title: 'bar', content: 'Include me!')
|
38
40
|
|
39
41
|
expect(@regular_model.title_is_foo).to eq [included]
|
40
42
|
|
41
|
-
included = BlogPost.create!(:
|
42
|
-
|
43
|
+
included = BlogPost.create!(title: 'foo', content: 'Include me!')
|
44
|
+
BlogPost.create!(title: 'bar', content: 'Include me!')
|
43
45
|
|
44
46
|
expect(BlogPost.title_is_foo).to eq [included]
|
45
47
|
end
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
49
|
-
context
|
51
|
+
context 'that has a polymorphic belongs_to' do
|
50
52
|
before do
|
51
53
|
animal = Class.new ActiveRecord::Base do
|
52
|
-
has_many :tea_cups, :
|
54
|
+
has_many :tea_cups, as: :pet
|
53
55
|
end
|
54
56
|
stub_const 'Animal', animal
|
55
57
|
end
|
56
58
|
|
57
59
|
with_model :TeaCup do
|
58
60
|
table do |t|
|
59
|
-
t.belongs_to :pet, :
|
61
|
+
t.belongs_to :pet, polymorphic: true, index: false
|
60
62
|
end
|
61
63
|
model do
|
62
|
-
belongs_to :pet, :
|
64
|
+
belongs_to :pet, polymorphic: true
|
63
65
|
end
|
64
66
|
end
|
65
67
|
|
@@ -67,20 +69,20 @@ describe "ActiveRecord behaviors" do
|
|
67
69
|
|
68
70
|
with_model :StuffedAnimal do
|
69
71
|
model do
|
70
|
-
has_many :tea_cups, :
|
72
|
+
has_many :tea_cups, as: :pet
|
71
73
|
end
|
72
74
|
end
|
73
75
|
|
74
|
-
describe
|
75
|
-
it
|
76
|
+
describe 'the polymorphic belongs_to' do
|
77
|
+
it 'works like a regular polymorphic belongs_to' do
|
76
78
|
animal = Animal.create!
|
77
79
|
stuffed_animal = StuffedAnimal.create!
|
78
80
|
|
79
|
-
tea_cup_for_animal = TeaCup.create!(:
|
81
|
+
tea_cup_for_animal = TeaCup.create!(pet: animal)
|
80
82
|
expect(tea_cup_for_animal.pet_type).to eq 'Animal'
|
81
83
|
expect(animal.tea_cups).to include(tea_cup_for_animal)
|
82
84
|
|
83
|
-
tea_cup_for_stuffed_animal = TeaCup.create!(:
|
85
|
+
tea_cup_for_stuffed_animal = TeaCup.create!(pet: stuffed_animal)
|
84
86
|
expect(tea_cup_for_stuffed_animal.pet_type).to eq 'StuffedAnimal'
|
85
87
|
expect(stuffed_animal.tea_cups).to include(tea_cup_for_stuffed_animal)
|
86
88
|
end
|
@@ -88,7 +90,7 @@ describe "ActiveRecord behaviors" do
|
|
88
90
|
end
|
89
91
|
end
|
90
92
|
|
91
|
-
context
|
93
|
+
context 'with an association' do
|
92
94
|
with_model :Province do
|
93
95
|
table do |t|
|
94
96
|
t.belongs_to :country
|
@@ -100,13 +102,13 @@ describe "ActiveRecord behaviors" do
|
|
100
102
|
|
101
103
|
with_model :Country
|
102
104
|
|
103
|
-
context
|
104
|
-
it
|
105
|
-
Province.create!(:
|
105
|
+
context 'in earlier examples' do
|
106
|
+
it 'works as normal' do
|
107
|
+
Province.create!(country: Country.create!)
|
106
108
|
end
|
107
109
|
end
|
108
110
|
|
109
|
-
context
|
111
|
+
context 'in later examples' do
|
110
112
|
it "does not hold a reference to earlier example groups' classes" do
|
111
113
|
expect(Province.reflect_on_association(:country).klass).to eq Country
|
112
114
|
end
|