fabrial 0.1.0 → 0.2.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: 84f5e2fcf01cf7ff1190a26ecea15da7b4220317
4
- data.tar.gz: ee79f497a4789c6a08dfb185af9735bf71077862
2
+ SHA256:
3
+ metadata.gz: bf013a11226fff5bf52dea812c36fcc95e8912f05d8118a8973727a7864125d6
4
+ data.tar.gz: 663a33a75e7e52a7e5f51be1476d0a250dc892a47fe0f8909b673fdeb7b6c23b
5
5
  SHA512:
6
- metadata.gz: ecb80b0451e0d77e6d136e5bc019559d3f275ee0bd06d50e286435fa0060037dddf5c7fb927fc6dc5a0053e8a1d25c81ba7fbda2cb51b6940242fddee2cd55ab
7
- data.tar.gz: 94f4ac89cd1a45d579d282b2de19167b2af9c5e1482539343d0f6271e16e37f676918eeaa65e2d828b920bfc5ec424a102212f607fd902bc89b8186d49adcc23
6
+ metadata.gz: 0b7bafadd06459481ddbc1e93e3598885976b9c1d93d44d8ac2319683554699f802f482988c3265c6dcf11df7ba27af4d45fafffecaf751dbc0b43ce9776f18f
7
+ data.tar.gz: 1949a259ec2c8f075241e54a11d9eebad8fde59473501af794b81e193772b26a331af245eeb36f14c247fe423f3b040881602a8115fce8d73a7263adb777cb01
data/.gitignore CHANGED
@@ -6,3 +6,7 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+
10
+ # Appraisal gemfiles
11
+ /gemfiles/.bundle/
12
+ /gemfiles/*.gemfile.lock
data/.rubocop.yml ADDED
@@ -0,0 +1,261 @@
1
+ inherit_mode:
2
+ merge:
3
+ - Exclude
4
+ - Include
5
+ - Whitelist
6
+ - Blacklist
7
+
8
+ AllCops:
9
+ DisplayStyleGuide: true
10
+ ExtraDetails: true
11
+ EnabledByDefault: true # Turn on all the cops!!
12
+ TargetRubyVersion: 2.3
13
+ Exclude:
14
+ - vendor/*
15
+ - gemfiles/**/*
16
+
17
+ # Cops
18
+ # ---------------------------------------------
19
+
20
+ #################### Layout ###########################
21
+
22
+ # I would like to turn this on, but the exception handling isn't good enough.
23
+ # It raises an offense on the first definition that doesn't match the config,
24
+ # and although you can disable there, if it is an earlier definition that threw
25
+ # it off, there's no way to disable the actual exceptional case.
26
+ #
27
+ # For example:
28
+ #
29
+ # has_many :dashboards, through: :packages
30
+ #
31
+ # # rubocop:disable ClassStructure <-- this disable doesn't help
32
+ # has_one :configuration, class_name: 'PracticeConfiguration'
33
+ # # Dynamic alias to catch method override below
34
+ # def practice_configuration # <-- out of order definition
35
+ # configuration
36
+ # end
37
+ # # rubocop:enable ClassStructure
38
+ #
39
+ # delegate :time_zone, to: :source # <-- offense raised here
40
+ #
41
+ # We'll want to keep an eye on this and see if it gets more capable over time.
42
+ Layout/ClassStructure:
43
+ Enabled: false
44
+
45
+ # I would like to turn this on, but it doesn't support two line method calls,
46
+ # and wants to turn this:
47
+ #
48
+ # method(really_long_parameter_name, really_long_parameter_name,
49
+ # really_long_parameter_name, really_long_parameter_name)
50
+ #
51
+ # into this:
52
+ #
53
+ # method(
54
+ # really_long_parameter_name,
55
+ # really_long_parameter_name,
56
+ # )
57
+ #
58
+ # At three lines I would like to switch styles, but two is too early
59
+ #
60
+ # I have opened an issue here: https://github.com/bbatsov/rubocop/issues/3393.
61
+ # If it is resolved, we can turn this on.
62
+ Layout/FirstMethodParameterLineBreak: { Enabled: false }
63
+
64
+ # These are similar to the above FirstMethodParameterLineBreak
65
+ Layout/FirstArrayElementLineBreak: { Enabled: false }
66
+ Layout/FirstHashElementLineBreak: { Enabled: false }
67
+ Layout/FirstMethodArgumentLineBreak: { Enabled: false }
68
+ Layout/MultilineMethodArgumentLineBreaks: { Enabled: false }
69
+ Layout/MultilineArrayLineBreaks: { Enabled: false }
70
+ Layout/MultilineHashKeyLineBreaks: { Enabled: false }
71
+
72
+ # This requires that function calls spanning multiple lines have the parameters
73
+ # line up. I only care if they are indented a little further.
74
+ Layout/AlignParameters: { Enabled: false }
75
+
76
+ # This requires that hashes spanning multiple lines have the elements
77
+ # line up. I only care if they are indented a little further.
78
+ Layout/AlignHash: { Enabled: false }
79
+
80
+ # This requires that arrays spanning multiple lines have the elements
81
+ # line up. I only care if they are indented a little further.
82
+ Layout/AlignArray: { Enabled: false }
83
+
84
+ Layout/MultilineAssignmentLayout: { Enabled: false } # Agreed, should be disabled
85
+
86
+ Layout/IndentFirstArrayElement: { EnforcedStyle: consistent }
87
+
88
+ Layout/EmptyLineBetweenDefs:
89
+ # If `true`, this parameter means that single line method definitions don't
90
+ # need an empty line between them.
91
+ AllowAdjacentOneLineDefs: true
92
+
93
+ # Sometimes we want to comment the arguments to a method and therefore need a
94
+ # blank line separating the commented arg from the rest. This would prevent
95
+ # that.
96
+ Layout/EmptyLinesAroundArguments: { Enabled: false }
97
+
98
+ # I would force the default mode `with_first_argument`, for all calls over 2
99
+ # lines if I could.
100
+ Layout/AlignArguments: { EnforcedStyle: with_fixed_indentation }
101
+
102
+ Layout/IndentFirstArgument: { EnforcedStyle: consistent }
103
+
104
+ Layout/MultilineOperationIndentation: { EnforcedStyle: indented }
105
+
106
+ Layout/MultilineMethodCallIndentation: { EnforcedStyle: indented }
107
+
108
+ #################### Lint ##################################
109
+
110
+ # This wants us to rewrite things like
111
+ #
112
+ # assert categories.any? { |c| c.appointment_category_id == 'GRM' }
113
+ #
114
+ # with
115
+ #
116
+ # assert(categories.any? { |c| c.appointment_category_id == 'GRM' })
117
+ #
118
+ # I don't like the extra parenthesis and expect our devs to know block
119
+ # precedence.
120
+ Lint/AmbiguousBlockAssociation: { Enabled: false }
121
+
122
+ Lint/NumberConversion: { Enabled: false } # I like `.to_i`
123
+
124
+ # Ignoring implicit references allows us to use the implicit passing of an
125
+ # argument to `super` to count as an argument reference, without causing an
126
+ # offense.
127
+ Lint/ShadowedArgument: { IgnoreImplicitReferences: true }
128
+
129
+ #################### Metrics ###############################
130
+
131
+ # Defaults to 100, we relax it a bit.
132
+ Metrics/ModuleLength: { Max: 150 }
133
+ Metrics/ClassLength: { Max: 150 }
134
+
135
+ # Defaults to 79, cut us a little slack
136
+ Metrics/LineLength: { Max: 89 }
137
+
138
+ # Defaults to 10, functions can be longer than 10 lines!!!
139
+ Metrics/MethodLength: { Max: 40 }
140
+
141
+ # Cut a bit more slack, but still warn on overly complex functions
142
+ Metrics/CyclomaticComplexity: { Max: 10 }
143
+
144
+ # Up the allowed complexity a little
145
+ Metrics/PerceivedComplexity: { Max: 10 }
146
+
147
+ # Increase max function size
148
+ Metrics/AbcSize: { Max: 50 }
149
+
150
+ ################## Migration #############################
151
+
152
+ # Agreed, should be off
153
+ Migration/DepartmentName: { Enabled: false }
154
+
155
+ #################### Naming ##############################
156
+
157
+ # This defaults to 'e', we like names a little more descriptive than that.
158
+ Naming/RescuedExceptionsVariableName: { PreferredName: err }
159
+
160
+ #################### Style ###############################
161
+
162
+ Style/Copyright: { Enabled: false } # we don't do copyright comments
163
+ Style/Documentation: { Enabled: false } # don't enforce documentation (classes)
164
+ Style/DocumentationMethod: { Enabled: false } # don't enforce documentation
165
+ Style/InlineComment: { Enabled: false } # I like trailing comments.
166
+ Style/MethodCallWithArgsParentheses: { Enabled: false } # I don't like parens
167
+ Style/MethodCalledOnDoEndBlock: { Enabled: false } # chaining is ok
168
+ Style/MissingElse: { Enabled: false } # else's not required
169
+ Style/Send: { Enabled: false } # send is ok
170
+ Style/StringHashKeys: { Enabled: false } # when we use strings, we mean to
171
+
172
+ # We prefer `rescue => e` to `rescue StandardError => e`. This is default Ruby
173
+ # behavior and we expect devs to know it.
174
+ Style/RescueStandardError: { EnforcedStyle: implicit }
175
+
176
+ # They default the arguments to [acc, elem], which, although more expressive,
177
+ # make it much harder to fit expressions on a single line.
178
+ Style/SingleLineBlockParams:
179
+ Methods:
180
+ - reduce: [a, e]
181
+ - inject: [a, e]
182
+
183
+ # I really like this one, but I cannot until they again support the
184
+ # MaxLineLength option. Without this, it forces us to write lines longer that
185
+ # 80 characters. I have an open issue here:
186
+ # https://github.com/rubocop-hq/rubocop/issues/6077
187
+ Style/IfUnlessModifier:
188
+ # MaxLineLength: 80
189
+ Enabled: false
190
+
191
+ # This prevents method chaining if the function takes a multiline block, I agree
192
+ # that those should be used carefully/spairingly to maintain readability, but in
193
+ # general, they are ok.
194
+ Style/MultilineBlockChain: { Enabled: false }
195
+
196
+ Style/TrailingCommaInArrayLiteral: { EnforcedStyleForMultiline: comma }
197
+
198
+ # I would love to turn this on, because I like the trailing comma, the problem
199
+ # is that it *always* wants a comma, which results in weird things like this:
200
+ # },
201
+ # },
202
+ # }
203
+ Style/TrailingCommaInHashLiteral:
204
+ Enabled: false
205
+ EnforcedStyleForMultiline: comma
206
+
207
+ # I would love to turn this on, because I like the trailing comma, the problem
208
+ # is that it *always* wants a comma, include if it is just a long single
209
+ # argument like this:
210
+ # group_concat(
211
+ # species.call.description
212
+ # .op('ORDER BY', species.call.description)
213
+ # .op('SEPARATOR', '||')
214
+ # .op('SEPARATOR', '||')*,*
215
+ # ).as(patient_species)
216
+ #
217
+ # I have opened an issue here: https://github.com/bbatsov/rubocop/issues/3392.
218
+ # We can enable this cop if/when it is resolved.
219
+ Style/TrailingCommaInArguments:
220
+ EnforcedStyleForMultiline: comma
221
+ Enabled: false
222
+
223
+ # The default here, nested, takes up WAY to much left indent space.
224
+ Style/ClassAndModuleChildren: { EnforcedStyle: compact }
225
+
226
+ # Use [] for array % literals that create arrays, () for ones that create single
227
+ # items, and {} for regex
228
+ Style/PercentLiteralDelimiters:
229
+ PreferredDelimiters:
230
+ '%': ()
231
+ '%i': '[]'
232
+ '%q': ()
233
+ '%Q': ()
234
+ '%r': '{}'
235
+ '%s': ()
236
+ '%w': '[]'
237
+ '%W': '[]'
238
+ '%x': ()
239
+
240
+ # `MinBodyLength` defines the number of lines of the a body of an if / unless
241
+ # needs to have to trigger this cop
242
+ Style/GuardClause: { MinBodyLength: 3 }
243
+
244
+ # Sometimes nesting if's can greatly improve readability
245
+ Style/IfInsideElse: { Enabled: false }
246
+
247
+ # I prefer methods with a few parenthesis as possible. This is a departure from
248
+ # the community style guide.
249
+ Style/NestedParenthesizedCalls: { Enabled: false }
250
+
251
+ # Based on the arguments from here:
252
+ # https://www.practicingruby.com/articles/ruby-and-the-singleton-pattern-dont-get-along,
253
+ # I now prefer using `extend self` over `module_function` (mostly because of the
254
+ # ability to define private methods). This is a departure from the community
255
+ # style guide here: https://github.com/bbatsov/ruby-style-guide#module-function,
256
+ # but the guide dosen't give any justification for its reasoning, so I'm
257
+ # comfortable defying it.
258
+ Style/ModuleFunction: { Enabled: false }
259
+
260
+ # Prefer `%{foo}` over `%<foo>s`
261
+ Style/FormatStringToken: { EnforcedStyle: template }
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ fabrial
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.3.8
data/.travis.yml CHANGED
@@ -1,5 +1,11 @@
1
- sudo: false
2
1
  language: ruby
3
- rvm:
4
- - 2.3.1
5
- before_install: gem install bundler -v 1.16.1
2
+ cache: bundler
3
+ script:
4
+ - bundle exec rubocop
5
+ - bundle exec rake
6
+
7
+ gemfile:
8
+ - gemfiles/activerecord_4.2.0.gemfile
9
+ - gemfiles/activerecord_5.0.2.gemfile
10
+ - gemfiles/activerecord_5.1.0.gemfile
11
+ - gemfiles/activerecord_5.2.2.gemfile
data/Appraisals ADDED
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ appraise 'activerecord_4.2.0' do
4
+ gem 'activerecord', '~> 4.2.0', require: 'active_record'
5
+ gem 'activesupport', '~> 4.2.0', require: 'active_support/all'
6
+ end
7
+
8
+ appraise 'activerecord_5.0.2' do
9
+ gem 'activerecord', '~> 5.0.2', require: 'active_record'
10
+ gem 'activesupport', '~> 5.0.2', require: 'active_support/all'
11
+ end
12
+
13
+ appraise 'activerecord_5.1.0' do
14
+ gem 'activerecord', '~> 5.1.0', require: 'active_record'
15
+ gem 'activesupport', '~> 5.1.0', require: 'active_support/all'
16
+ end
17
+
18
+ appraise 'activerecord_5.2.2' do
19
+ gem 'activerecord', '~> 5.2.2', require: 'active_record'
20
+ gem 'activesupport', '~> 5.2.2', require: 'active_support/all'
21
+ end
data/Gemfile CHANGED
@@ -1,6 +1,8 @@
1
- source "https://rubygems.org"
1
+ # frozen_string_literal: true
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
3
+ source 'https://rubygems.org'
4
+
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
6
 
5
7
  # Specify your gem's dependencies in fabrial.gemspec
6
8
  gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,89 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ fabrial (0.1.0)
5
+ activerecord (> 4.2.0, < 6.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activemodel (5.2.3)
11
+ activesupport (= 5.2.3)
12
+ activerecord (5.2.3)
13
+ activemodel (= 5.2.3)
14
+ activesupport (= 5.2.3)
15
+ arel (>= 9.0)
16
+ activesupport (5.2.3)
17
+ concurrent-ruby (~> 1.0, >= 1.0.2)
18
+ i18n (>= 0.7, < 2)
19
+ minitest (~> 5.1)
20
+ tzinfo (~> 1.1)
21
+ ansi (1.5.0)
22
+ appraisal (2.2.0)
23
+ bundler
24
+ rake
25
+ thor (>= 0.14.0)
26
+ arel (9.0.0)
27
+ ast (2.4.0)
28
+ builder (3.2.3)
29
+ byebug (11.0.1)
30
+ coderay (1.1.2)
31
+ concurrent-ruby (1.1.5)
32
+ database_cleaner (1.7.0)
33
+ i18n (1.7.0)
34
+ concurrent-ruby (~> 1.0)
35
+ jaro_winkler (1.5.3)
36
+ method_source (0.9.2)
37
+ minitest (5.12.2)
38
+ minitest-focus (1.1.2)
39
+ minitest (>= 4, < 6)
40
+ minitest-reporters (1.3.8)
41
+ ansi
42
+ builder
43
+ minitest (>= 5.0)
44
+ ruby-progressbar
45
+ parallel (1.17.0)
46
+ parser (2.6.5.0)
47
+ ast (~> 2.4.0)
48
+ pry (0.12.2)
49
+ coderay (~> 1.1.0)
50
+ method_source (~> 0.9.0)
51
+ pry-byebug (3.7.0)
52
+ byebug (~> 11.0)
53
+ pry (~> 0.10)
54
+ rainbow (3.0.0)
55
+ rake (13.0.0)
56
+ rubocop (0.75.0)
57
+ jaro_winkler (~> 1.5.1)
58
+ parallel (~> 1.10)
59
+ parser (>= 2.6)
60
+ rainbow (>= 2.2.2, < 4.0)
61
+ ruby-progressbar (~> 1.7)
62
+ unicode-display_width (>= 1.4.0, < 1.7)
63
+ ruby-progressbar (1.10.1)
64
+ sqlite3 (1.3.13)
65
+ thor (0.20.3)
66
+ thread_safe (0.3.6)
67
+ tzinfo (1.2.5)
68
+ thread_safe (~> 0.1)
69
+ unicode-display_width (1.6.0)
70
+
71
+ PLATFORMS
72
+ ruby
73
+
74
+ DEPENDENCIES
75
+ appraisal (~> 2.2, >= 2.2.0)
76
+ bundler (~> 1.0)
77
+ database_cleaner
78
+ fabrial!
79
+ minitest (~> 5.12, >= 5.12.2)
80
+ minitest-focus (~> 1.1, >= 1.1.2)
81
+ minitest-reporters (~> 1.3, >= 1.3.8)
82
+ pry
83
+ pry-byebug
84
+ rake (~> 13.0)
85
+ rubocop (~> 0.75.0)
86
+ sqlite3 (~> 1.3.0)
87
+
88
+ BUNDLED WITH
89
+ 1.17.3
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2018 Jeremy Mickelson
3
+ Copyright (c) 2019 AllyDVM INC.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,15 +1,12 @@
1
1
  # Fabrial
2
2
 
3
- COMMING SOON
3
+ ![Travis (.org)](https://img.shields.io/travis/allydvm/fabrial)
4
+ ![Gem](https://img.shields.io/gem/v/fabrial)
5
+ ![GitHub](https://img.shields.io/github/license/allydvm/fabrial)
4
6
 
5
- Fabrial makes it easy and pleasant to create your test data, directly inline
6
- with your tests, removing the need for hard to maintain fixture files or
7
- blueprints.
8
-
9
- Welcome to your new gem! In this directory, you'll find the files you need to be
10
- able to package up your Ruby library into a gem. Put your Ruby code in the file
11
- `lib/fabrial`. To experiment with that code, run `bin/console` for an
12
- interactive prompt.
7
+ Fabrial makes it easy to follow the "Arrange, Act, Assert" pattern in your tests.
8
+ It makes it trivial to create your test data directly inline with your tests;
9
+ removing the need for hard-to-maintain fixture files or blueprints.
13
10
 
14
11
  ## Installation
15
12
 
@@ -27,19 +24,9 @@ Or install it yourself as:
27
24
 
28
25
  $ gem install fabrial
29
26
 
30
- ## Usage
31
-
32
- TODO: Write usage instructions here
33
-
34
- ## Development
35
-
36
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
37
-
38
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
39
-
40
27
  ## Contributing
41
28
 
42
- Bug reports and pull requests are welcome on GitHub at https://github.com/CyborgMaster/fabrial.
29
+ Bug reports and pull requests are welcome on [GitHub](https://github.com/allydvm/fabrial).
43
30
 
44
31
  ## License
45
32
 
data/Rakefile CHANGED
@@ -1,10 +1,12 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rake/testtask'
3
5
 
4
6
  Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
7
- t.test_files = FileList["test/**/*_test.rb"]
7
+ t.libs << 'test'
8
+ t.libs << 'lib'
9
+ t.test_files = FileList['test/**/*_test.rb']
8
10
  end
9
11
 
10
- task :default => :test
12
+ task default: :test
data/bin/console CHANGED
@@ -1,14 +1,15 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require "bundler/setup"
4
- require "fabrial"
4
+ require 'bundler/setup'
5
+ require 'fabrial'
5
6
 
6
7
  # You can add fixtures and/or initialization code here to make experimenting
7
8
  # with your gem easier. You can also use a different console, if you like.
8
9
 
9
10
  # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
11
+ require 'pry'
12
+ Pry.start
12
13
 
13
- require "irb"
14
- IRB.start(__FILE__)
14
+ # require 'irb'
15
+ # IRB.start(__FILE__)
data/fabrial.gemspec CHANGED
@@ -1,25 +1,28 @@
1
- lib = File.expand_path("../lib", __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
2
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require "fabrial/version"
5
+ require 'fabrial/version'
4
6
 
5
7
  Gem::Specification.new do |spec|
6
- spec.name = "fabrial"
8
+ spec.name = 'fabrial'
7
9
  spec.version = Fabrial::VERSION
8
- spec.authors = ["Jeremy Mickelson"]
9
- spec.email = ["jeremy.mickelson@gmail.com"]
10
+ spec.authors = ['Jeremy Mickelson', 'Tad Thorley', 'Ralph Mickelson']
11
+ spec.email = ['jeremy.mickelson@gmail.com']
10
12
 
11
13
  spec.summary = 'Simply create test data inline with your tests'
12
14
  spec.description = <<~DESCRIPTION
13
- Fabrial makes it easy and pleasant to create your test data, directly inline
14
- with your tests, removing the need for hard to maintain fixture files or
15
- blueprints.
15
+ Fabrial makes it easy to follow the "Arrange, Act, Assert" pattern in your tests.
16
+ It makes it trivial to create your test data directly inline with your tests;
17
+ removing the need for hard-to-maintain fixture files or blueprints.
16
18
  DESCRIPTION
17
19
 
18
- spec.homepage = 'https://github.com/CyborgMaster/fabrial'
19
- spec.license = "MIT"
20
+ spec.homepage = 'https://github.com/allydvm/fabrial'
21
+ spec.license = 'MIT'
20
22
 
21
- # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
22
- # to allow pushing to a single host or delete this section to allow pushing to any host.
23
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the
24
+ # 'allowed_push_host' to allow pushing to a single host or delete this section to allow
25
+ # pushing to any host.
23
26
  # if spec.respond_to?(:metadata)
24
27
  # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
25
28
  # else
@@ -30,11 +33,23 @@ Gem::Specification.new do |spec|
30
33
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
31
34
  f.match(%r{^(test|spec|features)/})
32
35
  end
33
- spec.bindir = "exe"
36
+ spec.bindir = 'exe'
34
37
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
35
- spec.require_paths = ["lib"]
38
+ spec.require_paths = ['lib']
39
+
40
+ spec.required_ruby_version = '>= 2.3.8'
41
+
42
+ spec.add_dependency 'activerecord', '> 4.2.0', '< 6.0'
36
43
 
37
- spec.add_development_dependency "bundler", "~> 1.16"
38
- spec.add_development_dependency "rake", "~> 10.0"
39
- spec.add_development_dependency "minitest", "~> 5.0"
44
+ spec.add_development_dependency 'appraisal', '~> 2.2', '>= 2.2.0'
45
+ spec.add_development_dependency 'bundler', '~> 1.0'
46
+ spec.add_development_dependency 'database_cleaner'
47
+ spec.add_development_dependency 'minitest', '~> 5.12', '>= 5.12.2'
48
+ spec.add_development_dependency 'minitest-focus', '~> 1.1', '>= 1.1.2'
49
+ spec.add_development_dependency 'minitest-reporters', '~> 1.3', '>= 1.3.8'
50
+ spec.add_development_dependency 'pry'
51
+ spec.add_development_dependency 'pry-byebug'
52
+ spec.add_development_dependency 'rake', '~> 13.0'
53
+ spec.add_development_dependency 'rubocop', '~> 0.75.0'
54
+ spec.add_development_dependency 'sqlite3', '~> 1.3.0'
40
55
  end
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 4.2.0", require: "active_record"
6
+ gem "activesupport", "~> 4.2.0", require: "active_support/all"
7
+
8
+ gemspec path: "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 5.0.2", require: "active_record"
6
+ gem "activesupport", "~> 5.0.2", require: "active_support/all"
7
+
8
+ gemspec path: "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 5.1.0", require: "active_record"
6
+ gem "activesupport", "~> 5.1.0", require: "active_support/all"
7
+
8
+ gemspec path: "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 5.2.2", require: "active_record"
6
+ gem "activesupport", "~> 5.2.2", require: "active_support/all"
7
+
8
+ gemspec path: "../"
data/lib/fabrial.rb CHANGED
@@ -1,5 +1,39 @@
1
- require "fabrial/version"
1
+ # frozen_string_literal: true
2
+
3
+ require 'fabrial/version'
4
+ require 'fabrial/errors'
5
+ require 'fabrial/fabricate'
6
+ require 'fabrial/create'
2
7
 
3
8
  module Fabrial
4
- # Your code goes here...
9
+ extend Fabricate
10
+ extend Create
11
+ self.defaults = {}
12
+
13
+ @before_fabricate = nil
14
+ def self.before_fabricate(&block)
15
+ @before_fabricate = block
16
+ end
17
+
18
+ def self.run_before_fabricate(objects)
19
+ if @before_fabricate
20
+ @before_fabricate&.call objects
21
+ else
22
+ objects
23
+ end
24
+ end
25
+
26
+ @before_create = nil
27
+ def self.before_create(&block)
28
+ @before_create = block
29
+ end
30
+
31
+ def self.run_before_create(klass, data, ancesstors, children)
32
+ @before_create&.call klass, data, ancesstors, children
33
+ end
34
+
35
+ def self.reset
36
+ @before_fabricate = nil
37
+ @before_create = nil
38
+ end
5
39
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Create
4
+ attr_accessor :defaults
5
+
6
+ def create(klass, data = {})
7
+ # Find the base class of any STI types
8
+ base = klass.base_class
9
+
10
+ default_data = defaults[klass]
11
+ default_data ||= defaults[base]
12
+ default_data ||= {}
13
+
14
+ data = default_data.merge data
15
+ klass.create! data
16
+ end
17
+
18
+ module AutoIds
19
+ extend self
20
+
21
+ @ids = {}
22
+
23
+ # Get the next auto-incrementing id for the given klass
24
+ def next(klass)
25
+ id = @ids[klass] || 1
26
+ @ids[klass] += 1
27
+ id
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fabrial
4
+ class Error < RuntimeError; end
5
+ class UnknownClassError < Error; end
6
+ end
@@ -0,0 +1,232 @@
1
+ # frozen_string_literal: true
2
+
3
+ # TODO: properly hook up parent associations for pre-created objects passed in
4
+
5
+ module Fabrial::Fabricate
6
+ # Make expects a nested hash of type => data or [data]
7
+ def fabricate(objects)
8
+ objects = Fabrial.run_before_fabricate objects
9
+ add_default_return objects
10
+
11
+ ancestors = {}
12
+ returns = make_types objects, ancestors
13
+
14
+ # If returns is made up of pairs, return a hash.
15
+ if returns.first.is_a? Array
16
+ returns.to_h
17
+ else
18
+ returns.length <= 1 ? returns.first : returns
19
+ end
20
+ end
21
+
22
+ # If a return object(s) wasn't specified, default to returning the first
23
+ # object.
24
+ # TODO: Raise error if mixing array and hash return styles
25
+ def add_default_return(objects)
26
+ return if contains_return? objects
27
+
28
+ ret = objects.values.find do |v|
29
+ v.is_a?(Hash) || (v.is_a?(Array) && !v.empty?)
30
+ end
31
+ if ret
32
+ ret = ret.first if ret.is_a? Array
33
+ ret[:RETURN] = true
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def contains_return?(objects)
40
+ return false unless objects.is_a? Hash
41
+
42
+ objects.key?(:RETURN) || objects.any? do |_k, v|
43
+ v.is_a?(Hash) && contains_return?(v) ||
44
+ v.is_a?(Array) && v.any?(&method(:contains_return?))
45
+ end
46
+ end
47
+
48
+ # TO REMOVE;
49
+ # Setup default source and practice if not provided
50
+ # def add_defaults(objects)
51
+ # return objects if objects.delete :NO_DEFAULTS
52
+
53
+ # unless %i[source sources].any? { |k| objects.key? k }
54
+ # objects = { source: default_source.merge(objects) }
55
+ # end
56
+
57
+ # # We can only make a default practice if we are dealing with a single sync
58
+ # # client.
59
+ # source = objects[:source]
60
+ # if source.is_a?(Hash)
61
+ # unless %i[practice practices].any? { |p| source.key? p }
62
+ # children = extract_child_records Practice, source
63
+ # source[:practice] = default_practice.merge children
64
+ # end
65
+ # end
66
+
67
+ # objects
68
+ # end
69
+
70
+ # return_skip_levels allows us to skip created default practices and
71
+ # sources when choosing an object to return.
72
+ def make_types(objects, ancestors)
73
+ returns = []
74
+ objects.each do |type, data|
75
+ klass = get_class(type)
76
+ if klass.nil?
77
+ raise Fabrial::UnknownClassError, "Class #{type} does not exist"
78
+ end
79
+
80
+ returns.concat make_type klass, data, ancestors
81
+ end
82
+ returns
83
+ end
84
+
85
+ def make_type(klass, data_list, ancestors)
86
+ returns = []
87
+
88
+ # TODO: may need a hook here
89
+ # ::Maker.next_bank klass # Needed if we aren't in test
90
+
91
+ associations = collect_associations(klass, ancestors)
92
+ Array.wrap(data_list).each do |data|
93
+ should_return = data.delete :RETURN
94
+ children = extract_child_records klass, data
95
+ run_before_create klass, data, ancestors, children
96
+ object = make_object klass, data, associations
97
+
98
+ # Make sure new object is added as last item of ancestor hash
99
+ # collect_associations expects this in order to hook up polymorphic fields
100
+ next_ancestors = ancestors.dup.except klass
101
+ next_ancestors[klass] = object
102
+
103
+ if should_return
104
+ # If `RETURN` holds a value, use it as the key.
105
+ returns << if should_return == true
106
+ object
107
+ else
108
+ [should_return, object]
109
+ end
110
+ end
111
+
112
+ returns.concat make_types children, next_ancestors
113
+ end
114
+ returns
115
+ end
116
+
117
+ def make_object(klass, data, associations)
118
+ # Check for already created object
119
+ return data[:object] if data[:object]
120
+
121
+ type_col = klass.inheritance_column.try :to_sym
122
+ type = data.delete(type_col).try :safe_constantize
123
+ type ||= klass
124
+ create type, data.reverse_merge(associations)
125
+ end
126
+
127
+ def collect_associations(klass, ancestors)
128
+ associations = collect_parents(klass, ancestors)
129
+ if (p = polymorphic(klass))
130
+ associations[p] = ancestors.values.last
131
+ end
132
+ associations
133
+ end
134
+
135
+ def extract_child_records(klass, data)
136
+ children = data.select do |type, v|
137
+ # Must have nested data
138
+ [Array, Hash].any? { |c| v.is_a? c } &&
139
+ # Must be a class that we can instantiate
140
+ get_class(type) &&
141
+
142
+ # Even if it has the same name as a Model in the system, if it is also
143
+ # the name of a column in the table, assume the data is for a serialzed
144
+ # field and not a nested relation. Ex: Requests have a serialized field
145
+ # called content and there is also a Content model in the system.
146
+ (
147
+ # If they are using a class as the key, then always choose the class
148
+ # over the field.
149
+ type.is_a?(Class) ||
150
+
151
+ !column_names(klass).include?(type.to_s)
152
+ )
153
+ end
154
+ data.extract!(*children.keys)
155
+ end
156
+
157
+ def column_names(klass)
158
+ klass.column_names
159
+
160
+ # our project uses
161
+ # klass.column_names_including_stored
162
+ end
163
+
164
+ # TO REMOVE:
165
+ # def add_implicit_owner(klass, ancestors, children)
166
+ # {
167
+ # [Client, Patient] => Owner,
168
+ # [Enterprise, Practice] => EnterpriseMembership,
169
+ # }. each do |connected, connector|
170
+ # next unless (connected.delete klass) && (ancestors.key? connected[0])
171
+
172
+ # unless children.key? connector.name.demodulize.underscore.to_sym
173
+ # children.reverse_merge! connector => {}
174
+ # end
175
+ # end
176
+ # end
177
+
178
+ def collect_parents(klass, ancestors)
179
+ associations = klass.reflect_on_all_associations
180
+ polymorphics = associations.select(&:polymorphic?)
181
+ associations
182
+ .select do |a|
183
+ (!a.collection? || a.macro == :has_and_belongs_to_many) &&
184
+ !a.polymorphic? &&
185
+
186
+ # This is to throw out specified versions of polymorphic associations.
187
+ # Ex: Alert has a polymorphic association called `alertable` and two
188
+ # other associations, `alertable_patient` and `alertable_client` that
189
+ # allow joining to specific tables. These specified associations
190
+ # should be skipped.
191
+ polymorphics.none? do |other|
192
+ other != a && other.name.to_s == a.name.to_s.split('_').first
193
+ end
194
+ end
195
+ .select { |a| ancestors.key? a.klass } # Find ancestors that match
196
+ .map do |a| # Create data hash
197
+ if a.macro == :has_and_belongs_to_many
198
+ [a.name, [ancestors[a.klass]]]
199
+ else
200
+ [a.name, ancestors[a.klass]]
201
+ end
202
+ end.to_h
203
+ end
204
+
205
+ def polymorphic(klass)
206
+ klass.reflect_on_all_associations
207
+ .select(&:polymorphic?)
208
+ .map { |a| a.class_name.underscore.to_sym }[0]
209
+ end
210
+
211
+ def get_class(type)
212
+ return type if type.is_a? Class
213
+
214
+ type.to_s.classify.safe_constantize ||
215
+ type.to_s.classify.pluralize.safe_constantize
216
+ end
217
+
218
+ # TO REMOVE:
219
+ # DEFAULT_SOURCE_ID = -123
220
+ # public_constant :DEFAULT_SOURCE_ID
221
+ # def default_source
222
+ # c = Source.find_by id: DEFAULT_SOURCE_ID
223
+ # c ? { object: c } : { id: DEFAULT_SOURCE_ID }
224
+ # end
225
+ #
226
+ # DEFAULT_PRACTICE_ID = -456
227
+ # public_constant :DEFAULT_PRACTICE_ID
228
+ # def default_practice
229
+ # p = Practice.find_by id: DEFAULT_PRACTICE_ID
230
+ # p ? { object: p } : { id: DEFAULT_PRACTICE_ID }
231
+ # end
232
+ end
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Fabrial
2
- VERSION = "0.1.0"
4
+ VERSION = '0.2.0'
5
+ public_constant :VERSION
3
6
  end
metadata CHANGED
@@ -1,61 +1,219 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fabrial
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Mickelson
8
+ - Tad Thorley
9
+ - Ralph Mickelson
8
10
  autorequire:
9
11
  bindir: exe
10
12
  cert_chain: []
11
- date: 2018-05-04 00:00:00.000000000 Z
13
+ date: 2019-10-07 00:00:00.000000000 Z
12
14
  dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activerecord
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ">"
20
+ - !ruby/object:Gem::Version
21
+ version: 4.2.0
22
+ - - "<"
23
+ - !ruby/object:Gem::Version
24
+ version: '6.0'
25
+ type: :runtime
26
+ prerelease: false
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">"
30
+ - !ruby/object:Gem::Version
31
+ version: 4.2.0
32
+ - - "<"
33
+ - !ruby/object:Gem::Version
34
+ version: '6.0'
35
+ - !ruby/object:Gem::Dependency
36
+ name: appraisal
37
+ requirement: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: 2.2.0
42
+ - - "~>"
43
+ - !ruby/object:Gem::Version
44
+ version: '2.2'
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: 2.2.0
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.2'
13
55
  - !ruby/object:Gem::Dependency
14
56
  name: bundler
15
57
  requirement: !ruby/object:Gem::Requirement
16
58
  requirements:
17
59
  - - "~>"
18
60
  - !ruby/object:Gem::Version
19
- version: '1.16'
61
+ version: '1.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: database_cleaner
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: minitest
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '5.12'
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 5.12.2
20
93
  type: :development
21
94
  prerelease: false
22
95
  version_requirements: !ruby/object:Gem::Requirement
23
96
  requirements:
24
97
  - - "~>"
25
98
  - !ruby/object:Gem::Version
26
- version: '1.16'
99
+ version: '5.12'
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: 5.12.2
103
+ - !ruby/object:Gem::Dependency
104
+ name: minitest-focus
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '1.1'
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: 1.1.2
113
+ type: :development
114
+ prerelease: false
115
+ version_requirements: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - "~>"
118
+ - !ruby/object:Gem::Version
119
+ version: '1.1'
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: 1.1.2
123
+ - !ruby/object:Gem::Dependency
124
+ name: minitest-reporters
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: '1.3'
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: 1.3.8
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - "~>"
138
+ - !ruby/object:Gem::Version
139
+ version: '1.3'
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: 1.3.8
143
+ - !ruby/object:Gem::Dependency
144
+ name: pry
145
+ requirement: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
157
+ - !ruby/object:Gem::Dependency
158
+ name: pry-byebug
159
+ requirement: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - ">="
162
+ - !ruby/object:Gem::Version
163
+ version: '0'
164
+ type: :development
165
+ prerelease: false
166
+ version_requirements: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: '0'
27
171
  - !ruby/object:Gem::Dependency
28
172
  name: rake
29
173
  requirement: !ruby/object:Gem::Requirement
30
174
  requirements:
31
175
  - - "~>"
32
176
  - !ruby/object:Gem::Version
33
- version: '10.0'
177
+ version: '13.0'
34
178
  type: :development
35
179
  prerelease: false
36
180
  version_requirements: !ruby/object:Gem::Requirement
37
181
  requirements:
38
182
  - - "~>"
39
183
  - !ruby/object:Gem::Version
40
- version: '10.0'
184
+ version: '13.0'
41
185
  - !ruby/object:Gem::Dependency
42
- name: minitest
186
+ name: rubocop
43
187
  requirement: !ruby/object:Gem::Requirement
44
188
  requirements:
45
189
  - - "~>"
46
190
  - !ruby/object:Gem::Version
47
- version: '5.0'
191
+ version: 0.75.0
48
192
  type: :development
49
193
  prerelease: false
50
194
  version_requirements: !ruby/object:Gem::Requirement
51
195
  requirements:
52
196
  - - "~>"
53
197
  - !ruby/object:Gem::Version
54
- version: '5.0'
198
+ version: 0.75.0
199
+ - !ruby/object:Gem::Dependency
200
+ name: sqlite3
201
+ requirement: !ruby/object:Gem::Requirement
202
+ requirements:
203
+ - - "~>"
204
+ - !ruby/object:Gem::Version
205
+ version: 1.3.0
206
+ type: :development
207
+ prerelease: false
208
+ version_requirements: !ruby/object:Gem::Requirement
209
+ requirements:
210
+ - - "~>"
211
+ - !ruby/object:Gem::Version
212
+ version: 1.3.0
55
213
  description: |
56
- Fabrial makes it easy and pleasant to create your test data, directly inline
57
- with your tests, removing the need for hard to maintain fixture files or
58
- blueprints.
214
+ Fabrial makes it easy to follow the "Arrange, Act, Assert" pattern in your tests.
215
+ It makes it trivial to create your test data directly inline with your tests;
216
+ removing the need for hard-to-maintain fixture files or blueprints.
59
217
  email:
60
218
  - jeremy.mickelson@gmail.com
61
219
  executables: []
@@ -63,17 +221,29 @@ extensions: []
63
221
  extra_rdoc_files: []
64
222
  files:
65
223
  - ".gitignore"
224
+ - ".rubocop.yml"
225
+ - ".ruby-gemset"
226
+ - ".ruby-version"
66
227
  - ".travis.yml"
228
+ - Appraisals
67
229
  - Gemfile
230
+ - Gemfile.lock
68
231
  - LICENSE.txt
69
232
  - README.md
70
233
  - Rakefile
71
234
  - bin/console
72
235
  - bin/setup
73
236
  - fabrial.gemspec
237
+ - gemfiles/activerecord_4.2.0.gemfile
238
+ - gemfiles/activerecord_5.0.2.gemfile
239
+ - gemfiles/activerecord_5.1.0.gemfile
240
+ - gemfiles/activerecord_5.2.2.gemfile
74
241
  - lib/fabrial.rb
242
+ - lib/fabrial/create.rb
243
+ - lib/fabrial/errors.rb
244
+ - lib/fabrial/fabricate.rb
75
245
  - lib/fabrial/version.rb
76
- homepage: https://github.com/CyborgMaster/fabrial
246
+ homepage: https://github.com/allydvm/fabrial
77
247
  licenses:
78
248
  - MIT
79
249
  metadata: {}
@@ -85,15 +255,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
85
255
  requirements:
86
256
  - - ">="
87
257
  - !ruby/object:Gem::Version
88
- version: '0'
258
+ version: 2.3.8
89
259
  required_rubygems_version: !ruby/object:Gem::Requirement
90
260
  requirements:
91
261
  - - ">="
92
262
  - !ruby/object:Gem::Version
93
263
  version: '0'
94
264
  requirements: []
95
- rubyforge_project:
96
- rubygems_version: 2.6.11
265
+ rubygems_version: 3.0.6
97
266
  signing_key:
98
267
  specification_version: 4
99
268
  summary: Simply create test data inline with your tests