anonymous_active_record 1.0.4 → 1.0.5

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
2
  SHA256:
3
- metadata.gz: a4505db5d93ffbdacfffc19d27c14e1d98ca11a889660ff9587bea7590a99566
4
- data.tar.gz: 9afc59dff158716e7e1b303ab5e59978813857869170c14f672106e81b291424
3
+ metadata.gz: 4ca6f2f21fd0dcb0c001dec3dc5e95d3964677c7aff7f3541a99b4c606072b59
4
+ data.tar.gz: a6fb0dde8a98a253a57b9b4f24776fe935d4ad54ace7d553f6bdab272c207020
5
5
  SHA512:
6
- metadata.gz: 16dfd759bc5c9ec9ca06c116585cf9a20c62d2991cf627315a369a4e6fabce2c671c8b360dd77ef38de80efa4581e46652fbd2535d17e2d2e67274a897e5209f
7
- data.tar.gz: 0aaa90c93370fa1fab73b6c894f2eb0f00106706be3e772b490b8c2efc51533f132795b7b465890c7886b173a11db66d282e546f4ea02fe21aa7a5a31a751358
6
+ metadata.gz: cb02baf587332716753c3fa25a32d79c518ad2f7ed5777b2649b898c5882850f4bff0c3d5a28896927d5f57da0811df5e950b1a05f23407499408a77aefb6d1a
7
+ data.tar.gz: 60b28ea2ac93dc90df1e850902de70d7055c333749a3a0f55ece2ef557fbd74466de36febcbc193676de6039f809f7628e66c3daa7ab25177d83191f7e10460b
data/CODE_OF_CONDUCT.md CHANGED
@@ -1,74 +1,133 @@
1
+
1
2
  # Contributor Covenant Code of Conduct
2
3
 
3
4
  ## Our Pledge
4
5
 
5
- In the interest of fostering an open and welcoming environment, we as
6
- contributors and maintainers pledge to making participation in our project and
7
- our community a harassment-free experience for everyone, regardless of age, body
8
- size, disability, ethnicity, gender identity and expression, level of experience,
9
- nationality, personal appearance, race, religion, or sexual identity and
10
- orientation.
6
+ We as members, contributors, and leaders pledge to make participation in our
7
+ community a harassment-free experience for everyone, regardless of age, body
8
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
9
+ identity and expression, level of experience, education, socio-economic status,
10
+ nationality, personal appearance, race, religion, or sexual identity
11
+ and orientation.
12
+
13
+ We pledge to act and interact in ways that contribute to an open, welcoming,
14
+ diverse, inclusive, and healthy community.
11
15
 
12
16
  ## Our Standards
13
17
 
14
- Examples of behavior that contributes to creating a positive environment
15
- include:
18
+ Examples of behavior that contributes to a positive environment for our
19
+ community include:
16
20
 
17
- * Using welcoming and inclusive language
18
- * Being respectful of differing viewpoints and experiences
19
- * Gracefully accepting constructive criticism
20
- * Focusing on what is best for the community
21
- * Showing empathy towards other community members
21
+ * Demonstrating empathy and kindness toward other people
22
+ * Being respectful of differing opinions, viewpoints, and experiences
23
+ * Giving and gracefully accepting constructive feedback
24
+ * Accepting responsibility and apologizing to those affected by our mistakes,
25
+ and learning from the experience
26
+ * Focusing on what is best not just for us as individuals, but for the
27
+ overall community
22
28
 
23
- Examples of unacceptable behavior by participants include:
29
+ Examples of unacceptable behavior include:
24
30
 
25
- * The use of sexualized language or imagery and unwelcome sexual attention or
26
- advances
27
- * Trolling, insulting/derogatory comments, and personal or political attacks
31
+ * The use of sexualized language or imagery, and sexual attention or
32
+ advances of any kind
33
+ * Trolling, insulting or derogatory comments, and personal or political attacks
28
34
  * Public or private harassment
29
- * Publishing others' private information, such as a physical or electronic
30
- address, without explicit permission
35
+ * Publishing others' private information, such as a physical or email
36
+ address, without their explicit permission
31
37
  * Other conduct which could reasonably be considered inappropriate in a
32
38
  professional setting
33
39
 
34
- ## Our Responsibilities
40
+ ## Enforcement Responsibilities
35
41
 
36
- Project maintainers are responsible for clarifying the standards of acceptable
37
- behavior and are expected to take appropriate and fair corrective action in
38
- response to any instances of unacceptable behavior.
42
+ Community leaders are responsible for clarifying and enforcing our standards of
43
+ acceptable behavior and will take appropriate and fair corrective action in
44
+ response to any behavior that they deem inappropriate, threatening, offensive,
45
+ or harmful.
39
46
 
40
- Project maintainers have the right and responsibility to remove, edit, or
41
- reject comments, commits, code, wiki edits, issues, and other contributions
42
- that are not aligned to this Code of Conduct, or to ban temporarily or
43
- permanently any contributor for other behaviors that they deem inappropriate,
44
- threatening, offensive, or harmful.
47
+ Community leaders have the right and responsibility to remove, edit, or reject
48
+ comments, commits, code, wiki edits, issues, and other contributions that are
49
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
50
+ decisions when appropriate.
45
51
 
46
52
  ## Scope
47
53
 
48
- This Code of Conduct applies both within project spaces and in public spaces
49
- when an individual is representing the project or its community. Examples of
50
- representing a project or community include using an official project e-mail
51
- address, posting via an official social media account, or acting as an appointed
52
- representative at an online or offline event. Representation of a project may be
53
- further defined and clarified by project maintainers.
54
+ This Code of Conduct applies within all community spaces, and also applies when
55
+ an individual is officially representing the community in public spaces.
56
+ Examples of representing our community include using an official e-mail address,
57
+ posting via an official social media account, or acting as an appointed
58
+ representative at an online or offline event.
54
59
 
55
60
  ## Enforcement
56
61
 
57
62
  Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
- reported by contacting the project team at peter.boling@gmail.com. All
59
- complaints will be reviewed and investigated and will result in a response that
60
- is deemed necessary and appropriate to the circumstances. The project team is
61
- obligated to maintain confidentiality with regard to the reporter of an incident.
62
- Further details of specific enforcement policies may be posted separately.
63
+ reported to the community leaders responsible for enforcement at
64
+ [INSERT CONTACT METHOD].
65
+ All complaints will be reviewed and investigated promptly and fairly.
66
+
67
+ All community leaders are obligated to respect the privacy and security of the
68
+ reporter of any incident.
69
+
70
+ ## Enforcement Guidelines
71
+
72
+ Community leaders will follow these Community Impact Guidelines in determining
73
+ the consequences for any action they deem in violation of this Code of Conduct:
74
+
75
+ ### 1. Correction
76
+
77
+ **Community Impact**: Use of inappropriate language or other behavior deemed
78
+ unprofessional or unwelcome in the community.
79
+
80
+ **Consequence**: A private, written warning from community leaders, providing
81
+ clarity around the nature of the violation and an explanation of why the
82
+ behavior was inappropriate. A public apology may be requested.
83
+
84
+ ### 2. Warning
63
85
 
64
- Project maintainers who do not follow or enforce the Code of Conduct in good
65
- faith may face temporary or permanent repercussions as determined by other
66
- members of the project's leadership.
86
+ **Community Impact**: A violation through a single incident or series
87
+ of actions.
88
+
89
+ **Consequence**: A warning with consequences for continued behavior. No
90
+ interaction with the people involved, including unsolicited interaction with
91
+ those enforcing the Code of Conduct, for a specified period of time. This
92
+ includes avoiding interactions in community spaces as well as external channels
93
+ like social media. Violating these terms may lead to a temporary or
94
+ permanent ban.
95
+
96
+ ### 3. Temporary Ban
97
+
98
+ **Community Impact**: A serious violation of community standards, including
99
+ sustained inappropriate behavior.
100
+
101
+ **Consequence**: A temporary ban from any sort of interaction or public
102
+ communication with the community for a specified period of time. No public or
103
+ private interaction with the people involved, including unsolicited interaction
104
+ with those enforcing the Code of Conduct, is allowed during this period.
105
+ Violating these terms may lead to a permanent ban.
106
+
107
+ ### 4. Permanent Ban
108
+
109
+ **Community Impact**: Demonstrating a pattern of violation of community
110
+ standards, including sustained inappropriate behavior, harassment of an
111
+ individual, or aggression toward or disparagement of classes of individuals.
112
+
113
+ **Consequence**: A permanent ban from any sort of public interaction within
114
+ the community.
67
115
 
68
116
  ## Attribution
69
117
 
70
- This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
- available at [http://contributor-covenant.org/version/1/4][version]
118
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
119
+ version 2.0, available at
120
+ [https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0].
121
+
122
+ Community Impact Guidelines were inspired by
123
+ [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
124
+
125
+ For answers to common questions about this code of conduct, see the FAQ at
126
+ [https://www.contributor-covenant.org/faq][FAQ]. Translations are available
127
+ at [https://www.contributor-covenant.org/translations][translations].
72
128
 
73
- [homepage]: http://contributor-covenant.org
74
- [version]: http://contributor-covenant.org/version/1/4/
129
+ [homepage]: https://www.contributor-covenant.org
130
+ [v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html
131
+ [Mozilla CoC]: https://github.com/mozilla/diversity
132
+ [FAQ]: https://www.contributor-covenant.org/faq
133
+ [translations]: https://www.contributor-covenant.org/translations
data/README.md CHANGED
@@ -11,14 +11,14 @@ Warning: Use of this gem is a **security risk**, due to the use of Ruby's `eval`
11
11
  | download rank | [![Downloads Today](https://img.shields.io/gem/rd/anonymous_active_record.svg)](https://github.com/pboling/anonymous_active_record) |
12
12
  | version | [![Version](https://img.shields.io/gem/v/anonymous_active_record.svg)](https://rubygems.org/gems/anonymous_active_record) |
13
13
  | dependencies | [![Depfu](https://badges.depfu.com/badges/272ce0df3bc6df5cbea9354e2c3b65af/count.svg)](https://depfu.com/github/pboling/anonymous_active_record?project_id=5614) |
14
- | continuous integration | [![Build Status](https://travis-ci.org/pboling/anonymous_active_record.svg?branch=master)](https://travis-ci.org/pboling/anonymous_active_record) |
14
+ | continuous integration | [![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fpboling%2Fanonymous_active_record%2Fbadge&style=flat)](https://actions-badge.atrox.dev/pboling/anonymous_active_record/goto) |
15
15
  | test coverage | [![Test Coverage](https://api.codeclimate.com/v1/badges/fe504d4ab2fb77cecf7d/test_coverage)](https://codeclimate.com/github/pboling/anonymous_active_record/test_coverage) |
16
16
  | maintainability | [![Maintainability](https://api.codeclimate.com/v1/badges/fe504d4ab2fb77cecf7d/maintainability)](https://codeclimate.com/github/pboling/anonymous_active_record/maintainability) |
17
17
  | code triage | [![Open Source Helpers](https://www.codetriage.com/pboling/anonymous_active_record/badges/users.svg)](https://www.codetriage.com/pboling/anonymous_active_record) |
18
18
  | FOSSA Licenses | [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fpboling%2Fanonymous_active_record.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fpboling%2Fanonymous_active_record?ref=badge_shield) |
19
19
  | homepage | [on Github.com][homepage], [on Railsbling.com][blogpage] |
20
20
  | documentation | [on RDoc.info][documentation] |
21
- | Spread ~♡ⓛⓞⓥⓔ♡~ | [🌍 🌎 🌏](https://about.me/peter.boling), [🍚](https://www.crowdrise.com/helprefugeeswithhopefortomorrowliberia/fundraiser/peterboling), [➕](https://plus.google.com/+PeterBoling/posts), [👼](https://angel.co/peter-boling), [🐛](https://www.topcoder.com/members/pboling/), [:shipit:](http://coderwall.com/pboling), [![Tweet Peter](https://img.shields.io/twitter/follow/galtzo.svg?style=social&label=Follow)](http://twitter.com/galtzo) |
21
+ | Spread ~♡ⓛⓞⓥⓔ♡~ | [🌏](https://about.me/peter.boling), [👼](https://angel.co/peter-boling), [:shipit:](http://coderwall.com/pboling), [![Tweet Peter](https://img.shields.io/twitter/follow/galtzo.svg?style=social&label=Follow)](http://twitter.com/galtzo), [🌹](https://nationalprogressiveparty.org) |
22
22
 
23
23
  ## Installation
24
24
 
@@ -44,8 +44,8 @@ module AnonymousActiveRecord
44
44
  }.freeze
45
45
 
46
46
  # Defines a pseudo anonymous class in a particular namespace of your choosing.
47
- def generate(table_name: nil, klass_namespaces: [], klass_basename: nil, columns: [], indexes: [], timestamps: true, connection_params: DEFAULT_CONNECTION_PARAMS, &block)
48
- gen = AnonymousActiveRecord::Generator.new(table_name, klass_namespaces, klass_basename)
47
+ def generate(table_name: nil, klass_namespaces: [], klass_basename: nil, columns: [], indexes: [], timestamps: true, parent_klass: "ActiveRecord::Base", connection_params: DEFAULT_CONNECTION_PARAMS, &block)
48
+ gen = AnonymousActiveRecord::Generator.new(table_name, klass_namespaces, klass_basename, parent_klass)
49
49
  klass = gen.generate(&block)
50
50
  connection_params = YAML.load_file(connection_params) if connection_params.is_a?(String)
51
51
  klass.establish_connection(connection_params.dup)
@@ -70,7 +70,7 @@ module AnonymousActiveRecord
70
70
  if idx_options.length == 1
71
71
  t.index idx_options[0]
72
72
  else
73
- t.index idx_options[0], idx_options[-1]
73
+ t.index idx_options[0], **idx_options[-1]
74
74
  end
75
75
  else
76
76
  t.index idx_options
@@ -82,21 +82,21 @@ module AnonymousActiveRecord
82
82
  end
83
83
 
84
84
  # Initializes instances of a pseudo anonymous class in a particular namespace of your choosing.
85
- def factory(source_data: [], table_name: nil, klass_namespaces: [], klass_basename: nil, columns: [], indexes: [], timestamps: true, connection_params: DEFAULT_CONNECTION_PARAMS, &block)
86
- factory = _factory(source_data: source_data, table_name: table_name, klass_namespaces: klass_namespaces, klass_basename: klass_basename, columns: columns, indexes: indexes, timestamps: timestamps, connection_params: connection_params, &block)
85
+ def factory(source_data: [], table_name: nil, klass_namespaces: [], klass_basename: nil, columns: [], indexes: [], timestamps: true, parent_klass: "ActiveRecord::Base", connection_params: DEFAULT_CONNECTION_PARAMS, &block)
86
+ factory = _factory(source_data: source_data, table_name: table_name, klass_namespaces: klass_namespaces, klass_basename: klass_basename, columns: columns, indexes: indexes, timestamps: timestamps, parent_klass: parent_klass, connection_params: connection_params, &block)
87
87
  factory.run
88
88
  end
89
89
 
90
90
  # Initializes instances of a pseudo anonymous class in a particular namespace of your choosing.
91
- def factory!(source_data: [], table_name: nil, klass_namespaces: [], klass_basename: nil, columns: [], indexes: [], timestamps: true, connection_params: DEFAULT_CONNECTION_PARAMS, &block)
92
- factory = _factory(source_data: source_data, table_name: table_name, klass_namespaces: klass_namespaces, klass_basename: klass_basename, columns: columns, indexes: indexes, timestamps: timestamps, connection_params: connection_params, &block)
91
+ def factory!(source_data: [], table_name: nil, klass_namespaces: [], klass_basename: nil, columns: [], indexes: [], timestamps: true, parent_klass: "ActiveRecord::Base", connection_params: DEFAULT_CONNECTION_PARAMS, &block)
92
+ factory = _factory(source_data: source_data, table_name: table_name, klass_namespaces: klass_namespaces, klass_basename: klass_basename, columns: columns, indexes: indexes, timestamps: timestamps, parent_klass: parent_klass, connection_params: connection_params, &block)
93
93
  factory.run!
94
94
  end
95
95
 
96
96
  private
97
97
 
98
- def _factory(source_data: [], table_name: nil, klass_namespaces: [], klass_basename: nil, columns: [], indexes: [], timestamps: true, connection_params: DEFAULT_CONNECTION_PARAMS, &block)
99
- klass = generate(table_name: table_name, klass_namespaces: klass_namespaces, klass_basename: klass_basename, columns: columns, timestamps: timestamps, indexes: indexes, connection_params: connection_params, &block)
98
+ def _factory(source_data: [], table_name: nil, klass_namespaces: [], klass_basename: nil, columns: [], indexes: [], timestamps: true, parent_klass: "ActiveRecord::Base", connection_params: DEFAULT_CONNECTION_PARAMS, &block)
99
+ klass = generate(table_name: table_name, klass_namespaces: klass_namespaces, klass_basename: klass_basename, columns: columns, timestamps: timestamps, parent_klass: parent_klass, indexes: indexes, connection_params: connection_params, &block)
100
100
  AnonymousActiveRecord::Factory.new(source_data, klass)
101
101
  end
102
102
 
@@ -16,14 +16,15 @@ module AnonymousActiveRecord
16
16
  class Generator
17
17
  DEFAULT_NAME = 'anons'
18
18
 
19
- attr_reader :klass_namespaces, :table_name, :klass_name
19
+ attr_reader :klass_namespaces, :table_name, :klass_name, :parent_klass
20
20
 
21
- def initialize(table_name, klass_namespaces = [], klass_basename = nil)
21
+ def initialize(table_name, klass_namespaces = [], klass_basename = nil, parent_klass = "ActiveRecord::Base")
22
22
  @klass_namespaces = Array(klass_namespaces).map(&:to_s).map { |x| x.gsub(/[^a-z0-9]+/i, '_') }
23
23
  klass_context = [(klass_basename || DEFAULT_NAME).gsub(/[^a-z0-9]+/i, '_').capitalize, SecureRandom.uuid.gsub(/[^a-z0-9]+/i, '_')].join('_')
24
24
  @table_name = (table_name || klass_context).downcase.to_s
25
25
  # String#capitalize is Ruby >= 2.4, https://stackoverflow.com/a/3725154/213191
26
26
  @klass_name = (klass_namespaces << klass_context).join('::')
27
+ @parent_klass = parent_klass
27
28
  end
28
29
 
29
30
  def generate(&block)
@@ -31,7 +32,7 @@ module AnonymousActiveRecord
31
32
  # Class.new(ActiveRecord::Base)
32
33
  # which was useful for specs, and other use cases. But it is now explicitly not supported, see
33
34
  # https://github.com/rails/rails/issues/8934
34
- eval "class ::#{klass_name} < ActiveRecord::Base; end"
35
+ eval "class ::#{klass_name} < #{parent_klass}; end"
35
36
  klass = Kernel.const_get(klass_name, true)
36
37
  klass.class_eval(&block) if block_given?
37
38
  klass.table_name = table_name
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AnonymousActiveRecord
4
- VERSION = '1.0.4'
4
+ VERSION = '1.0.5'
5
5
  end
@@ -0,0 +1,977 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe AnonymousActiveRecord do
4
+ it 'has a version number' do
5
+ expect(AnonymousActiveRecord::VERSION).not_to be nil
6
+ end
7
+
8
+ describe '.generate' do
9
+ context 'minimal params' do
10
+ subject { described_class.generate }
11
+
12
+ it 'does not error' do
13
+ expect { subject }.not_to raise_error
14
+ end
15
+ context 'instance' do
16
+ subject { super().new }
17
+
18
+ it 'can be instantiated' do
19
+ expect(subject).to be_a(ActiveRecord::Base)
20
+ end
21
+ context 'timestamps' do
22
+ it 'has' do
23
+ expect(subject.created_at).to be_nil
24
+ expect(subject.updated_at).to be_nil
25
+ end
26
+ end
27
+
28
+ context 'saving' do
29
+ subject do
30
+ i = super()
31
+ i.save
32
+ i
33
+ end
34
+
35
+ it 'does not error' do
36
+ expect { subject }.not_to raise_error
37
+ end
38
+ it 'does not have name' do
39
+ expect(subject).not_to respond_to(:name)
40
+ end
41
+ it 'sets timestamps' do
42
+ expect(subject.created_at).not_to be_nil
43
+ expect(subject.updated_at).not_to be_nil
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ context 'all params' do
50
+ subject do
51
+ described_class.generate(
52
+ table_name: table_name,
53
+ klass_namespaces: klass_namespaces,
54
+ klass_basename: klass_basename,
55
+ columns: columns,
56
+ indexes: indexes,
57
+ timestamps: timestamps,
58
+ connection_params: connection_params
59
+ )
60
+ end
61
+
62
+ let!(:farm_animal) do
63
+ module Farm
64
+ module Animal
65
+ end
66
+ end
67
+ end
68
+ let(:table_name) { 'dogs' }
69
+ let(:klass_namespaces) { %w[Farm Animal] }
70
+ let(:klass_basename) { 'my' }
71
+ let(:columns) { ['name'] }
72
+ let(:indexes) { [{ columns: ['name'] }] }
73
+ let(:timestamps) { true }
74
+ let(:connection_params) { AnonymousActiveRecord::DEFAULT_CONNECTION_PARAMS }
75
+
76
+ it 'does not error' do
77
+ expect { subject }.not_to raise_error
78
+ end
79
+ context 'instance' do
80
+ subject { super().new }
81
+
82
+ it 'can be instantiated' do
83
+ expect(subject).to be_a(ActiveRecord::Base)
84
+ end
85
+ context 'name' do
86
+ it 'has' do
87
+ expect(subject.name).to be_nil
88
+ end
89
+ end
90
+
91
+ context 'timestamps' do
92
+ it 'has' do
93
+ expect(subject.created_at).to be_nil
94
+ expect(subject.updated_at).to be_nil
95
+ end
96
+ end
97
+
98
+ context 'saving' do
99
+ subject do
100
+ i = super()
101
+ i.name = 'Bobo'
102
+ i.save
103
+ i
104
+ end
105
+
106
+ it 'does not error' do
107
+ expect { subject }.not_to raise_error
108
+ end
109
+ it 'sets name' do
110
+ expect(subject.name).to eq('Bobo')
111
+ end
112
+ it 'sets timestamps' do
113
+ expect(subject.created_at).not_to be_nil
114
+ expect(subject.updated_at).not_to be_nil
115
+ end
116
+ end
117
+ end
118
+ end
119
+
120
+ context 'designating type' do
121
+ subject do
122
+ described_class.generate(
123
+ table_name: table_name,
124
+ klass_namespaces: klass_namespaces,
125
+ klass_basename: klass_basename,
126
+ columns: columns,
127
+ indexes: indexes,
128
+ timestamps: timestamps,
129
+ connection_params: connection_params
130
+ )
131
+ end
132
+
133
+ let!(:farm_animal) do
134
+ module Farm
135
+ module Animal
136
+ end
137
+ end
138
+ end
139
+ let(:table_name) { 'dogs' }
140
+ let(:klass_namespaces) { %w[Farm Animal] }
141
+ let(:klass_basename) { 'my' }
142
+ let(:columns) { [{ name: 'name', type: 'string' }, { name: 'baked_at', type: 'time' }] }
143
+ let(:indexes) { [] }
144
+ let(:timestamps) { true }
145
+ let(:connection_params) { AnonymousActiveRecord::DEFAULT_CONNECTION_PARAMS }
146
+
147
+ it 'does not error' do
148
+ expect { subject }.not_to raise_error
149
+ end
150
+ context 'instance' do
151
+ subject { super().new }
152
+
153
+ it 'can be instantiated' do
154
+ expect(subject).to be_a(ActiveRecord::Base)
155
+ end
156
+ context 'name' do
157
+ it 'has' do
158
+ expect(subject.name).to be_nil
159
+ end
160
+ end
161
+
162
+ context 'baked_at' do
163
+ it 'has' do
164
+ expect(subject.baked_at).to be_nil
165
+ end
166
+ end
167
+
168
+ context 'timestamps' do
169
+ it 'has' do
170
+ expect(subject.created_at).to be_nil
171
+ expect(subject.updated_at).to be_nil
172
+ end
173
+ end
174
+
175
+ context 'saving' do
176
+ subject do
177
+ i = super()
178
+ i.name = 'Bobo'
179
+ i.baked_at = Time.now
180
+ i.save
181
+ i
182
+ end
183
+
184
+ it 'does not error' do
185
+ expect { subject }.not_to raise_error
186
+ end
187
+ it 'sets name' do
188
+ expect(subject.name).to eq('Bobo')
189
+ end
190
+ it 'sets baked_at' do
191
+ expect([ActiveRecord::Type::Time::Value, Time]).to include(subject.baked_at.class)
192
+ end
193
+ it 'sets timestamps' do
194
+ expect(subject.created_at).not_to be_nil
195
+ expect(subject.updated_at).not_to be_nil
196
+ end
197
+ end
198
+ end
199
+ end
200
+
201
+ context 'designating default' do
202
+ subject do
203
+ described_class.generate(
204
+ table_name: table_name,
205
+ klass_namespaces: klass_namespaces,
206
+ klass_basename: klass_basename,
207
+ columns: columns,
208
+ indexes: indexes,
209
+ timestamps: timestamps,
210
+ connection_params: connection_params
211
+ )
212
+ end
213
+
214
+ let!(:farm_animal) do
215
+ module Farm
216
+ module Animal
217
+ end
218
+ end
219
+ end
220
+ let(:table_name) { 'dogs' }
221
+ let(:klass_namespaces) { %w[Farm Animal] }
222
+ let(:klass_basename) { 'my' }
223
+ let(:columns) { [{ name: 'name', type: 'string', default: 'Bird Man' }, { name: 'number', type: 'integer', default: 0 }] }
224
+ let(:indexes) { [] }
225
+ let(:timestamps) { true }
226
+ let(:connection_params) { AnonymousActiveRecord::DEFAULT_CONNECTION_PARAMS }
227
+
228
+ it 'does not error' do
229
+ expect { subject }.not_to raise_error
230
+ end
231
+ context 'instance' do
232
+ subject { super().new }
233
+
234
+ it 'can be instantiated' do
235
+ expect(subject).to be_a(ActiveRecord::Base)
236
+ end
237
+ context 'name' do
238
+ it 'has' do
239
+ expect(subject.name).to eq('Bird Man')
240
+ end
241
+ end
242
+
243
+ context 'number' do
244
+ it 'has' do
245
+ expect(subject.number).to eq(0)
246
+ end
247
+ end
248
+
249
+ context 'timestamps' do
250
+ it 'has' do
251
+ expect(subject.created_at).to be_nil
252
+ expect(subject.updated_at).to be_nil
253
+ end
254
+ end
255
+
256
+ context 'saving' do
257
+ subject do
258
+ i = super()
259
+ i.name = 'Bobo'
260
+ i.number += 111
261
+ i.save
262
+ i
263
+ end
264
+
265
+ it 'does not error' do
266
+ expect { subject }.not_to raise_error
267
+ end
268
+ it 'sets name' do
269
+ expect(subject.name).to eq('Bobo')
270
+ end
271
+ it 'sets number' do
272
+ expect(subject.number).to eq(111)
273
+ end
274
+ it 'sets timestamps' do
275
+ expect(subject.created_at).not_to be_nil
276
+ expect(subject.updated_at).not_to be_nil
277
+ end
278
+ end
279
+ end
280
+ end
281
+
282
+ context 'with unique index as options' do
283
+ subject do
284
+ described_class.generate(
285
+ table_name: table_name,
286
+ klass_namespaces: klass_namespaces,
287
+ klass_basename: klass_basename,
288
+ columns: columns,
289
+ indexes: indexes,
290
+ timestamps: timestamps,
291
+ connection_params: connection_params
292
+ )
293
+ end
294
+
295
+ let!(:farm_animal) do
296
+ module Farm
297
+ module Animal
298
+ end
299
+ end
300
+ end
301
+ let(:table_name) { 'dogs' }
302
+ let(:klass_namespaces) { %w[Farm Animal] }
303
+ let(:klass_basename) { 'my' }
304
+ let(:columns) { [{ name: 'name', type: 'string' }, { name: 'baked_at', type: 'time' }] }
305
+ let(:indexes) { [{ columns: ['name'], unique: true }, { columns: ['baked_at'] }] }
306
+ let(:timestamps) { true }
307
+ let(:connection_params) { AnonymousActiveRecord::DEFAULT_CONNECTION_PARAMS }
308
+
309
+ it 'does not error' do
310
+ expect { subject }.not_to raise_error
311
+ end
312
+ context 'instance' do
313
+ subject { super().new }
314
+
315
+ it 'can be instantiated' do
316
+ expect(subject).to be_a(ActiveRecord::Base)
317
+ end
318
+ context 'name' do
319
+ it 'has' do
320
+ expect(subject.name).to be_nil
321
+ end
322
+ end
323
+
324
+ context 'baked_at' do
325
+ it 'has' do
326
+ expect(subject.baked_at).to be_nil
327
+ end
328
+ end
329
+
330
+ context 'timestamps' do
331
+ it 'has' do
332
+ expect(subject.created_at).to be_nil
333
+ expect(subject.updated_at).to be_nil
334
+ end
335
+ end
336
+
337
+ context 'saving' do
338
+ subject do
339
+ i = super()
340
+ i.name = 'Bobo'
341
+ i.baked_at = Time.now
342
+ i.save
343
+ i
344
+ end
345
+
346
+ it 'does not error' do
347
+ expect { subject }.not_to raise_error
348
+ end
349
+ it 'sets name' do
350
+ expect(subject.name).to eq('Bobo')
351
+ end
352
+ it 'sets baked_at' do
353
+ expect([ActiveRecord::Type::Time::Value, Time]).to include(subject.baked_at.class)
354
+ end
355
+ it 'sets timestamps' do
356
+ expect(subject.created_at).not_to be_nil
357
+ expect(subject.updated_at).not_to be_nil
358
+ end
359
+ end
360
+
361
+ context 'uniqueness enforced by index' do
362
+ subject do
363
+ i = model.new
364
+ i.name = 'Bobo'
365
+ i.baked_at = Time.now
366
+ i.save!
367
+ end
368
+
369
+ let(:model) do
370
+ described_class.generate(
371
+ table_name: table_name,
372
+ klass_namespaces: klass_namespaces,
373
+ klass_basename: klass_basename,
374
+ columns: columns,
375
+ indexes: indexes,
376
+ timestamps: timestamps,
377
+ connection_params: connection_params
378
+ )
379
+ end
380
+
381
+ before do
382
+ i = model.new
383
+ i.name = 'Bobo'
384
+ i.baked_at = Time.now
385
+ i.save
386
+ end
387
+
388
+ it 'raises error' do
389
+ block_is_expected.to raise_error(ActiveRecord::RecordNotUnique)
390
+ end
391
+ end
392
+ end
393
+ end
394
+
395
+ context 'with unique index as implicit' do
396
+ subject do
397
+ described_class.generate(
398
+ table_name: table_name,
399
+ klass_namespaces: klass_namespaces,
400
+ klass_basename: klass_basename,
401
+ columns: columns,
402
+ indexes: indexes,
403
+ timestamps: timestamps,
404
+ connection_params: connection_params
405
+ )
406
+ end
407
+
408
+ let!(:farm_animal) do
409
+ module Farm
410
+ module Animal
411
+ end
412
+ end
413
+ end
414
+ let(:table_name) { 'dogs' }
415
+ let(:klass_namespaces) { %w[Farm Animal] }
416
+ let(:klass_basename) { 'my' }
417
+ let(:columns) { [{ name: 'name', type: 'string' }, { name: 'baked_at', type: 'time' }] }
418
+ let(:indexes) { [[['name'], unique: true], 'baked_at'] }
419
+ let(:timestamps) { true }
420
+ let(:connection_params) { AnonymousActiveRecord::DEFAULT_CONNECTION_PARAMS }
421
+
422
+ it 'does not error' do
423
+ expect { subject }.not_to raise_error
424
+ end
425
+ context 'instance' do
426
+ subject { super().new }
427
+
428
+ it 'can be instantiated' do
429
+ expect(subject).to be_a(ActiveRecord::Base)
430
+ end
431
+ context 'name' do
432
+ it 'has' do
433
+ expect(subject.name).to be_nil
434
+ end
435
+ end
436
+
437
+ context 'baked_at' do
438
+ it 'has' do
439
+ expect(subject.baked_at).to be_nil
440
+ end
441
+ end
442
+
443
+ context 'timestamps' do
444
+ it 'has' do
445
+ expect(subject.created_at).to be_nil
446
+ expect(subject.updated_at).to be_nil
447
+ end
448
+ end
449
+
450
+ context 'saving' do
451
+ subject do
452
+ i = super()
453
+ i.name = 'Bobo'
454
+ i.baked_at = Time.now
455
+ i.save
456
+ i
457
+ end
458
+
459
+ it 'does not error' do
460
+ expect { subject }.not_to raise_error
461
+ end
462
+ it 'sets name' do
463
+ expect(subject.name).to eq('Bobo')
464
+ end
465
+ it 'sets baked_at' do
466
+ expect([ActiveRecord::Type::Time::Value, Time]).to include(subject.baked_at.class)
467
+ end
468
+ it 'sets timestamps' do
469
+ expect(subject.created_at).not_to be_nil
470
+ expect(subject.updated_at).not_to be_nil
471
+ end
472
+ end
473
+
474
+ context 'uniqueness enforced by index' do
475
+ subject do
476
+ i = model.new
477
+ i.name = 'Bobo'
478
+ i.baked_at = Time.now
479
+ i.save!
480
+ end
481
+
482
+ let(:model) do
483
+ described_class.generate(
484
+ table_name: table_name,
485
+ klass_namespaces: klass_namespaces,
486
+ klass_basename: klass_basename,
487
+ columns: columns,
488
+ indexes: indexes,
489
+ timestamps: timestamps,
490
+ connection_params: connection_params
491
+ )
492
+ end
493
+
494
+ before do
495
+ i = model.new
496
+ i.name = 'Bobo'
497
+ i.baked_at = Time.now
498
+ i.save
499
+ end
500
+
501
+ it 'raises error' do
502
+ block_is_expected.to raise_error(ActiveRecord::RecordNotUnique)
503
+ end
504
+ end
505
+ end
506
+ end
507
+
508
+ context 'no timestamps' do
509
+ subject do
510
+ described_class.generate(
511
+ table_name: table_name,
512
+ klass_basename: klass_basename,
513
+ columns: columns,
514
+ timestamps: timestamps,
515
+ connection_params: connection_params
516
+ )
517
+ end
518
+
519
+ let(:table_name) { 'dogs' }
520
+ let(:klass_basename) { 'my' }
521
+ let(:columns) { ['name'] }
522
+ let(:timestamps) { false }
523
+ let(:connection_params) { AnonymousActiveRecord::DEFAULT_CONNECTION_PARAMS }
524
+
525
+ it 'does not error' do
526
+ expect { subject }.not_to raise_error
527
+ end
528
+ context 'instance' do
529
+ subject { super().new }
530
+
531
+ it 'can be instantiated' do
532
+ expect(subject).to be_a(ActiveRecord::Base)
533
+ end
534
+ context 'timestamps' do
535
+ it 'has not' do
536
+ expect(subject).not_to respond_to(:created_at)
537
+ expect(subject).not_to respond_to(:updated_at)
538
+ end
539
+ end
540
+
541
+ context 'saving' do
542
+ subject do
543
+ i = super()
544
+ i.name = 'Bobo'
545
+ i.save
546
+ i
547
+ end
548
+
549
+ it 'does not error' do
550
+ expect { subject }.not_to raise_error
551
+ end
552
+ it 'sets name' do
553
+ expect(subject.name).to eq('Bobo')
554
+ end
555
+ it 'has no timestamps' do
556
+ expect(subject).not_to respond_to(:created_at)
557
+ expect(subject).not_to respond_to(:updated_at)
558
+ end
559
+ end
560
+ end
561
+ end
562
+
563
+ context 'with block' do
564
+ subject do
565
+ described_class.generate(
566
+ table_name: table_name,
567
+ klass_basename: klass_basename,
568
+ columns: columns,
569
+ timestamps: timestamps,
570
+ connection_params: connection_params
571
+ ) do
572
+ def eat_pie
573
+ 'eating'
574
+ end
575
+
576
+ def flowery_name
577
+ "🌸#{name}🌸"
578
+ end
579
+ end
580
+ end
581
+
582
+ let(:table_name) { 'dogs' }
583
+ let(:klass_basename) { 'my' }
584
+ let(:columns) { ['name'] }
585
+ let(:timestamps) { false }
586
+ let(:connection_params) { AnonymousActiveRecord::DEFAULT_CONNECTION_PARAMS }
587
+
588
+ it 'does not error' do
589
+ expect { subject }.not_to raise_error
590
+ end
591
+ context 'instance' do
592
+ subject { super().new(name: 'Marty McFly') }
593
+
594
+ it 'can be instantiated' do
595
+ expect(subject).to be_a(ActiveRecord::Base)
596
+ end
597
+ context 'block' do
598
+ it 'defines method' do
599
+ expect(subject.eat_pie).to eq('eating')
600
+ end
601
+ it 'has access to class context' do
602
+ expect(subject.flowery_name).to eq('🌸Marty McFly🌸')
603
+ end
604
+ end
605
+
606
+ context 'timestamps' do
607
+ it 'has not' do
608
+ expect(subject).not_to respond_to(:created_at)
609
+ expect(subject).not_to respond_to(:updated_at)
610
+ end
611
+ end
612
+
613
+ context 'saving' do
614
+ subject do
615
+ i = super()
616
+ i.name = 'Bobo'
617
+ i.save
618
+ i
619
+ end
620
+
621
+ it 'does not error' do
622
+ expect { subject }.not_to raise_error
623
+ end
624
+ it 'sets name' do
625
+ expect(subject.name).to eq('Bobo')
626
+ end
627
+ it 'has access to class context' do
628
+ expect(subject.flowery_name).to eq('🌸Bobo🌸')
629
+ end
630
+ it 'has no timestamps' do
631
+ expect(subject).not_to respond_to(:created_at)
632
+ expect(subject).not_to respond_to(:updated_at)
633
+ end
634
+ end
635
+ end
636
+ end
637
+
638
+ context 'testing a module' do
639
+ let!(:has_balloon) do
640
+ module HasBalloon
641
+ def has_balloon?
642
+ name == 'Spot' # only Spot has a balloon
643
+ end
644
+ end
645
+ end
646
+ let(:ar_with_balloon) do
647
+ described_class.generate(columns: ['name']) do
648
+ include HasBalloon
649
+ def flowery_name
650
+ "#{b_f}#{name}#{b_f}"
651
+ end
652
+
653
+ def b_f
654
+ has_balloon? ? '🎈' : '🌸'
655
+ end
656
+ end
657
+ end
658
+
659
+ it 'can test the module' do
660
+ expect(ar_with_balloon.new(name: 'Spot').flowery_name).to eq('🎈Spot🎈')
661
+ expect(ar_with_balloon.new(name: 'Not Spot').flowery_name).to eq('🌸Not Spot🌸')
662
+ end
663
+ end
664
+ end
665
+
666
+ describe '.factory' do
667
+ context 'minimal params' do
668
+ context 'returns array' do
669
+ subject { described_class.factory }
670
+
671
+ it 'be an array' do
672
+ expect(subject).to be_a(Array)
673
+ end
674
+ it 'has length 0' do
675
+ expect(subject.length).to eq(0)
676
+ end
677
+ end
678
+ end
679
+
680
+ context 'all params' do
681
+ subject do
682
+ described_class.factory(
683
+ source_data: source_data,
684
+ table_name: table_name,
685
+ klass_namespaces: klass_namespaces,
686
+ klass_basename: klass_basename,
687
+ columns: columns,
688
+ indexes: indexes,
689
+ timestamps: timestamps,
690
+ connection_params: connection_params
691
+ )
692
+ end
693
+
694
+ let!(:farm_animal) do
695
+ module Zoo
696
+ module Animal
697
+ end
698
+ end
699
+ end
700
+ let(:table_name) { 'dogs' }
701
+ let(:klass_namespaces) { %w[Zoo Animal] }
702
+ let(:klass_basename) { 'my' }
703
+ let(:columns) { ['name'] }
704
+ let(:indexes) { [{ columns: ['name'] }] }
705
+ let(:timestamps) { true }
706
+ let(:source_data) { [{ name: 'Gru Banksy' }, { name: 'Herlina Termalina' }] }
707
+ let(:connection_params) { AnonymousActiveRecord::DEFAULT_CONNECTION_PARAMS }
708
+
709
+ context 'returns array' do
710
+ it 'be an array' do
711
+ expect(subject).to be_a(Array)
712
+ end
713
+ it 'has length 2' do
714
+ expect(subject.length).to eq(2)
715
+ end
716
+ end
717
+
718
+ context 'sets attributes' do
719
+ subject { super().map(&:name) }
720
+
721
+ it 'be an array' do
722
+ expect(subject).to eq(['Gru Banksy', 'Herlina Termalina'])
723
+ end
724
+ end
725
+ end
726
+
727
+ context 'no timestamps' do
728
+ subject do
729
+ described_class.factory(
730
+ source_data: source_data,
731
+ table_name: table_name,
732
+ klass_basename: klass_basename,
733
+ columns: columns,
734
+ indexes: indexes,
735
+ timestamps: timestamps,
736
+ connection_params: connection_params
737
+ )
738
+ end
739
+
740
+ let(:table_name) { 'dogs' }
741
+ let(:klass_basename) { 'my' }
742
+ let(:columns) { ['name'] }
743
+ let(:indexes) { [{ columns: ['name'] }] }
744
+ let(:timestamps) { false }
745
+ let(:source_data) { [{ name: 'Gru Banksy' }, { name: 'Herlina Termalina' }] }
746
+ let(:connection_params) { AnonymousActiveRecord::DEFAULT_CONNECTION_PARAMS }
747
+
748
+ context 'returns array' do
749
+ it 'be an array' do
750
+ expect(subject).to be_a(Array)
751
+ end
752
+ it 'has length 2' do
753
+ expect(subject.length).to eq(2)
754
+ end
755
+ end
756
+
757
+ context 'does not have timestamps' do
758
+ subject { super().map { |anon| anon.respond_to?(:created_at) } }
759
+
760
+ it 'be an array' do
761
+ expect(subject).to eq([false, false])
762
+ end
763
+ end
764
+ end
765
+
766
+ context 'with block' do
767
+ subject do
768
+ described_class.factory(
769
+ source_data: source_data,
770
+ table_name: table_name,
771
+ klass_basename: klass_basename,
772
+ columns: columns,
773
+ indexes: indexes,
774
+ timestamps: timestamps,
775
+ connection_params: connection_params
776
+ ) do
777
+ def eat_pie
778
+ 'eating'
779
+ end
780
+
781
+ def flowery_name
782
+ "🌸#{name}🌸"
783
+ end
784
+ end
785
+ end
786
+
787
+ let(:table_name) { 'dogs' }
788
+ let(:klass_basename) { 'my' }
789
+ let(:columns) { ['name'] }
790
+ let(:indexes) { [{ columns: ['name'] }] }
791
+ let(:timestamps) { false }
792
+ let(:source_data) { [{ name: 'Gru Banksy' }, { name: 'Herlina Termalina' }] }
793
+ let(:connection_params) { AnonymousActiveRecord::DEFAULT_CONNECTION_PARAMS }
794
+
795
+ context 'returns array' do
796
+ it 'be an array' do
797
+ expect(subject).to be_a(Array)
798
+ end
799
+ it 'has length 2' do
800
+ expect(subject.length).to eq(2)
801
+ end
802
+ end
803
+
804
+ context 'defines method' do
805
+ subject { super().map(&:eat_pie) }
806
+
807
+ it 'defines method' do
808
+ expect(subject).to eq(%w[eating eating])
809
+ end
810
+ end
811
+
812
+ context 'sets attributes' do
813
+ subject { super().map(&:flowery_name) }
814
+
815
+ it 'be an array' do
816
+ expect(subject).to eq(['🌸Gru Banksy🌸', '🌸Herlina Termalina🌸'])
817
+ end
818
+ end
819
+ end
820
+ end
821
+
822
+ describe '.factory!' do
823
+ context 'minimal params' do
824
+ context 'returns array' do
825
+ subject { described_class.factory! }
826
+
827
+ it 'be an array' do
828
+ expect(subject).to be_a(Array)
829
+ end
830
+ it 'has length 0' do
831
+ expect(subject.length).to eq(0)
832
+ end
833
+ end
834
+ end
835
+
836
+ context 'all params' do
837
+ subject do
838
+ described_class.factory!(
839
+ source_data: source_data,
840
+ table_name: table_name,
841
+ klass_namespaces: klass_namespaces,
842
+ klass_basename: klass_basename,
843
+ columns: columns,
844
+ indexes: indexes,
845
+ timestamps: timestamps,
846
+ connection_params: connection_params
847
+ )
848
+ end
849
+
850
+ let!(:farm_animal) do
851
+ module Zoo
852
+ module Animal
853
+ end
854
+ end
855
+ end
856
+ let(:table_name) { 'dogs' }
857
+ let(:klass_namespaces) { %w[Zoo Animal] }
858
+ let(:klass_basename) { 'my' }
859
+ let(:columns) { ['name'] }
860
+ let(:indexes) { [{ columns: ['name'] }] }
861
+ let(:timestamps) { true }
862
+ let(:source_data) { [{ name: 'Gru Banksy' }, { name: 'Herlina Termalina' }] }
863
+ let(:connection_params) { AnonymousActiveRecord::DEFAULT_CONNECTION_PARAMS }
864
+
865
+ context 'returns array' do
866
+ it 'be an array' do
867
+ expect(subject).to be_a(Array)
868
+ end
869
+ it 'has length 2' do
870
+ expect(subject.length).to eq(2)
871
+ end
872
+ end
873
+
874
+ context 'sets attributes' do
875
+ subject { super().map(&:name) }
876
+
877
+ it 'be an array' do
878
+ expect(subject).to eq(['Gru Banksy', 'Herlina Termalina'])
879
+ end
880
+ end
881
+ end
882
+
883
+ context 'no timestamps' do
884
+ subject do
885
+ described_class.factory!(
886
+ source_data: source_data,
887
+ table_name: table_name,
888
+ klass_basename: klass_basename,
889
+ columns: columns,
890
+ indexes: indexes,
891
+ timestamps: timestamps,
892
+ connection_params: connection_params
893
+ )
894
+ end
895
+
896
+ let(:table_name) { 'dogs' }
897
+ let(:klass_basename) { 'my' }
898
+ let(:columns) { ['name'] }
899
+ let(:indexes) { [{ columns: ['name'] }] }
900
+ let(:timestamps) { false }
901
+ let(:source_data) { [{ name: 'Gru Banksy' }, { name: 'Herlina Termalina' }] }
902
+ let(:connection_params) { AnonymousActiveRecord::DEFAULT_CONNECTION_PARAMS }
903
+
904
+ context 'returns array' do
905
+ it 'be an array' do
906
+ expect(subject).to be_a(Array)
907
+ end
908
+ it 'has length 2' do
909
+ expect(subject.length).to eq(2)
910
+ end
911
+ end
912
+
913
+ context 'does not have timestamps' do
914
+ subject { super().map { |anon| anon.respond_to?(:created_at) } }
915
+
916
+ it 'be an array' do
917
+ expect(subject).to eq([false, false])
918
+ end
919
+ end
920
+ end
921
+
922
+ context 'with block' do
923
+ subject do
924
+ described_class.factory!(
925
+ source_data: source_data,
926
+ table_name: table_name,
927
+ klass_basename: klass_basename,
928
+ columns: columns,
929
+ indexes: indexes,
930
+ timestamps: timestamps,
931
+ connection_params: connection_params
932
+ ) do
933
+ def eat_pie
934
+ 'eating'
935
+ end
936
+
937
+ def flowery_name
938
+ "🌸#{name}🌸"
939
+ end
940
+ end
941
+ end
942
+
943
+ let(:table_name) { 'dogs' }
944
+ let(:klass_basename) { 'my' }
945
+ let(:columns) { ['name'] }
946
+ let(:indexes) { [{ columns: ['name'] }] }
947
+ let(:timestamps) { false }
948
+ let(:source_data) { [{ name: 'Gru Banksy' }, { name: 'Herlina Termalina' }] }
949
+ let(:connection_params) { AnonymousActiveRecord::DEFAULT_CONNECTION_PARAMS }
950
+
951
+ context 'returns array' do
952
+ it 'be an array' do
953
+ expect(subject).to be_a(Array)
954
+ end
955
+ it 'has length 2' do
956
+ expect(subject.length).to eq(2)
957
+ end
958
+ end
959
+
960
+ context 'defines method' do
961
+ subject { super().map(&:eat_pie) }
962
+
963
+ it 'defines method' do
964
+ expect(subject).to eq(%w[eating eating])
965
+ end
966
+ end
967
+
968
+ context 'sets attributes' do
969
+ subject { super().map(&:flowery_name) }
970
+
971
+ it 'be an array' do
972
+ expect(subject).to eq(['🌸Gru Banksy🌸', '🌸Herlina Termalina🌸'])
973
+ end
974
+ end
975
+ end
976
+ end
977
+ end