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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: acf677d36c3ecf81055a163f81197487363d9e30
4
- data.tar.gz: 4a2592965f7f7daad7bd87f3ebeb1d4a966042ad
2
+ SHA256:
3
+ metadata.gz: 22f429a5cb8e986623de65004594810d642f7ca21b0bf24a0a1257defa40add9
4
+ data.tar.gz: a7a0cbbe47ba722b1359a438c18692a7927ff957c88cd0e0919ac3ab4ac65e92
5
5
  SHA512:
6
- metadata.gz: 2740903c7eb9e1694e73a1e2dea1a8f50dedee100c182e1d499fce75bb6a12d42a6448c65cf3e674bb8c5dfd68829514acecdc52acab9c4463dd2da62e03e538
7
- data.tar.gz: 2770e5fb17c776135c589606e89e85c5c45df341aecca576bc8304a233dc82ebe0ad614b2fcaed4af98c306068a66f23c9714f317596e6839f234f831cb02e22
6
+ metadata.gz: 63d816a1fe0782ee315073325b6eb59b468bc87c7899f3a124c181cc6542ee9c31d55768a3e2af8234ec6ffad9bb92037b012da5328128e835fce4a74d7a6b15
7
+ data.tar.gz: 6da66d3cbf860d19d5a2c661e01e75ff7aef341d78d64d12055d5c28ebc5e7401ea5c095b6b006da1c01bcb4b2100bf524681a63292ccf791cff7def6a987115
@@ -0,0 +1,6 @@
1
+ inherit_gem:
2
+ lint-config-ruby:
3
+ - default.yml
4
+
5
+ AllCops:
6
+ TargetRubyVersion: 2.3
@@ -2,36 +2,42 @@ language: ruby
2
2
  sudo: false
3
3
 
4
4
  rvm:
5
- - "2.3.3"
6
- - "2.2.6"
7
- - "2.1.10"
8
- - jruby-9.1.6.0
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
- - ACTIVE_RECORD_BRANCH="4-2-stable"
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: "2.1.10"
30
+ - rvm: 2.3.7
27
31
  env: ACTIVE_RECORD_BRANCH="master"
28
- - rvm: "2.1.10"
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.1.6.0
35
- env: ACTIVE_RECORD_BRANCH="5-0-stable"
36
- - rvm: jruby-9.1.6.0
37
- env: ACTIVE_RECORD_VERSION="~> 5.0.0"
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
- if ar_branch = ENV['ACTIVE_RECORD_BRANCH']
6
- gem 'activerecord', :git => 'https://github.com/rails/rails.git', :branch => ENV['ACTIVE_RECORD_BRANCH']
7
- gem 'arel', :git => 'https://github.com/rails/arel.git' if ar_branch == 'master'
8
- end
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 ENV['ACTIVE_RECORD_VERSION']
11
- gem 'activerecord', ENV['ACTIVE_RECORD_VERSION']
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-2016 Case Commons, Inc. <http://casecommons.org>
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
- before :all do
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 works just like a migration.
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 works just like the class definition.
57
+ # The model block is the ActiveRecord model’s class body.
62
58
  model do
63
- include SomeModule
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?(SomeModule)).to eq true
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
- As of version 1.0.0, with_model uses [Semantic Versioning 2.0.0](http://semver.org/spec/v2.0.0.html). Previous versions used an ad-hoc versioning scheme.
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–2016 [Case Commons, Inc](http://casecommons.org).
174
+ Copyright © 2010–2018 [Case Commons, Inc](http://casecommons.org).
179
175
  Licensed under the MIT license, see [LICENSE](/LICENSE) file.
@@ -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]
@@ -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')
@@ -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, options = {}, &block)
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, options = {}, &block)
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 const_name
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 value
9
- if Object.const_defined?(@const_name)
10
- @original_value = Object.const_get(@const_name)
11
- Object.send :remove_const, @const_name
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
- Object.const_set @const_name, value
18
+ @namespace.const_set basename, value
15
19
  end
16
20
 
17
21
  def unstub_const
18
- Object.send :remove_const, @const_name
19
- Object.const_set @const_name, @original_value if @original_value
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WithModel
2
4
  module Methods
3
5
  def with_model?
@@ -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 name, options = {}
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 = options.fetch(:superclass, ActiveRecord::Base)
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 = "#$$_#{Thread.current.object_id}"
72
- "with_model_#{@name.to_s.tableize}_#{uid}".freeze
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
@@ -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 model
6
+ def initialize(model)
5
7
  @model = model
6
8
  end
7
9
 
8
- def table options = {}, &block
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
- def model &block
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
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_record'
2
4
 
3
5
  module WithModel
4
6
  class Table
5
- def initialize name, options = {}, &block
7
+ def initialize(name, options = {}, &block)
6
8
  @name = name.freeze
7
9
  @options = options.freeze
8
10
  @block = block
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WithModel
2
- VERSION = '2.0.0'.freeze
4
+ VERSION = '2.1.0'
3
5
  end
@@ -1,11 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
- describe "ActiveRecord behaviors" do
4
- describe "a temporary ActiveRecord model created with with_model" do
5
- context "that has a named scope" do
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, lambda { where(:title => '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, lambda { where(:title => 'foo') }
32
+ scope :title_is_foo, -> { where(title: 'foo') }
31
33
  end
32
34
  end
33
35
 
34
- describe "the named scope" do
35
- it "works like a regular named scope" do
36
- included = @regular_model.create!(:title => 'foo', :content => 'Include me!')
37
- excluded = @regular_model.create!(:title => 'bar', :content => 'Include me!')
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!(:title => 'foo', :content => 'Include me!')
42
- excluded = BlogPost.create!(:title => 'bar', :content => 'Include me!')
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 "that has a polymorphic belongs_to" do
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, :as => :pet
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, :polymorphic => true, :index => false
61
+ t.belongs_to :pet, polymorphic: true, index: false
60
62
  end
61
63
  model do
62
- belongs_to :pet, :polymorphic => true
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, :as => :pet
72
+ has_many :tea_cups, as: :pet
71
73
  end
72
74
  end
73
75
 
74
- describe "the polymorphic belongs_to" do
75
- it "works like a regular polymorphic belongs_to" do
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!(:pet => animal)
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!(:pet => stuffed_animal)
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 "with an association" do
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 "in earlier examples" do
104
- it "works as normal" do
105
- Province.create!(:country => Country.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 "in later examples" do
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