fabrial 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 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