with_model 2.0.0 → 2.1.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 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