brick 1.0.34 → 1.0.35

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
2
  SHA256:
3
- metadata.gz: 9d1e2f8b6ff7ca3fa7fcd129c33de3dfe6e674b6da154b9a64e094c65a3a152a
4
- data.tar.gz: 30e39f62458a46854f56b2a6decbfe5ea42a4bb5325e81ed76f21400aae8e252
3
+ metadata.gz: 34a23d1057771acea1beb9ea1ea2ff3d27e5983084bcd47f4c87686af77328d5
4
+ data.tar.gz: 44aea0d5fb92a361913ba4a17ebca62cf5be9aca5585fa9785b7c388c2652cee
5
5
  SHA512:
6
- metadata.gz: 14c6bae09e34f53126e2003cbc7256c4b32f4a4219d42f1f7e94ca83211debf3704fa6c170cd6231d89e26eb168f282d1dea7eff7150ef1a013364aeb4eb65c3
7
- data.tar.gz: 7f33aa5c89be2e8401f4cda0ea6cecb6e01639934a2df1e7b00bd88d065bf3cc9b748bebb1691d51c1b04114fba3b1739a7820c7614f4eb84d52494bd4cc769e
6
+ metadata.gz: e9124cbd0db47816db2dcbf59a76adcc0d4dcaea8f4ad02ea9ee99aace025c8914a7871c78a4a703f4daeced7dbaec12d52fdf56b6bc131c4c855be931d4f838
7
+ data.tar.gz: 671d0333b9a89870db67cdec05306311475724d674aab494c794baa0648736c873ea2aade170bdbc51642b96e4fe76a19f568bf31e724bd513230e1a78c69521
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_record/version'
4
+
5
+ # ActiveRecord before 4.0 didn't have #version
6
+ unless ActiveRecord.respond_to?(:version)
7
+ module ActiveRecord
8
+ def self.version
9
+ ::Gem::Version.new(ActiveRecord::VERSION::STRING)
10
+ end
11
+ end
12
+ end
13
+
14
+ # In ActiveSupport older than 5.0, the duplicable? test tries to new up a BigDecimal,
15
+ # and Ruby 2.6 and later deprecates #new. This removes the warning from BigDecimal.
16
+ # This compatibility needs to be put into place in the application's "config/boot.rb"
17
+ # file by having the line "require 'brick/compatibility'" to be the last line in that
18
+ # file.
19
+ require 'bigdecimal'
20
+ if ::Gem::Version.new(RUBY_VERSION) >= ::Gem::Version.new('2.6') &&
21
+ ActiveRecord.version < ::Gem::Version.new('5.0')
22
+ def BigDecimal.new(*args, **kwargs)
23
+ BigDecimal(*args, **kwargs)
24
+ end
25
+ end
@@ -203,7 +203,9 @@ module ActiveRecord
203
203
  model_underscore = name.underscore
204
204
  assoc_name = CGI.escapeHTML(assoc_name.to_s)
205
205
  model_path = Rails.application.routes.url_helpers.send("#{model_underscore.tr('/', '_').pluralize}_path".to_sym)
206
- link = Class.new.extend(ActionView::Helpers::UrlHelper).link_to(name, model_path)
206
+ av_class = Class.new.extend(ActionView::Helpers::UrlHelper)
207
+ av_class.extend(ActionView::Helpers::TagHelper) if ActionView.version < ::Gem::Version.new('6.1')
208
+ link = av_class.link_to(name, model_path)
207
209
  model_underscore == assoc_name ? link : "#{assoc_name}-#{link}".html_safe
208
210
  end
209
211
 
@@ -409,7 +411,6 @@ module ActiveRecord
409
411
  hm_counts.each do |k, hm|
410
412
  associative = nil
411
413
  count_column = if hm.options[:through]
412
- # binding.pry if associatives[hm.name].nil?
413
414
  fk_col = (associative = associatives[hm.name]).foreign_key
414
415
  hm.foreign_key
415
416
  else
@@ -500,8 +501,9 @@ if ActiveSupport::Dependencies.respond_to?(:autoload_module!) # %%% Only works w
500
501
  alias _brick_autoload_module! autoload_module!
501
502
  def autoload_module!(*args)
502
503
  into, const_name, qualified_name, path_suffix = args
503
- base_class_name = ::Brick.config.sti_namespace_prefixes&.fetch("::#{into.name}::", nil)
504
- base_class_name = "::#{base_class_name}" unless base_class_name.start_with?('::')
504
+ if (base_class_name = ::Brick.config.sti_namespace_prefixes&.fetch("::#{into.name}::", nil))
505
+ base_class_name = "::#{base_class_name}" unless base_class_name.start_with?('::')
506
+ end
505
507
  if (base_class = base_class_name&.constantize)
506
508
  ::Brick.sti_models[qualified_name] = { base: base_class }
507
509
  # Build subclass and place it into the specially STI-namespaced module
@@ -777,9 +779,12 @@ class Object
777
779
  options = { through: through.to_sym }
778
780
  if relation[:fks].any? { |k, v| v[:assoc_name] == hmt_name }
779
781
  hmt_name = "#{hmt_name.singularize}_#{fk.first[:assoc_name]}"
780
- # binding.pry if relation[:fks].any? { |k, v| v[:assoc_name] == hmt_name }
781
- options[:class_name] = fk.first[:inverse_table].singularize.camelize
782
- options[:foreign_key] = fk.first[:fk].to_sym
782
+ # Was:
783
+ # options[:class_name] = fk.first[:inverse_table].singularize.camelize
784
+ # options[:foreign_key] = fk.first[:fk].to_sym
785
+ far_assoc = relations[fk.first[:inverse_table]][:fks].find { |_k, v| v[:assoc_name] == fk.last }
786
+ options[:class_name] = far_assoc.last[:inverse_table].singularize.camelize
787
+ options[:foreign_key] = far_assoc.last[:fk].to_sym
783
788
  end
784
789
  options[:source] = fk.last.to_sym unless hmt_name.singularize == fk.last
785
790
  code << " has_many :#{hmt_name}#{options.map { |opt| ", #{opt.first}: #{opt.last.inspect}" }.join}\n"
@@ -942,7 +947,6 @@ class Object
942
947
  }
943
948
  s
944
949
  end
945
- # binding.pry
946
950
  render inline: json.to_json, content_type: request.format
947
951
  return
948
952
  end
@@ -959,7 +963,8 @@ class Object
959
963
  return
960
964
  end
961
965
 
962
- order = pk.each_with_object([]) { |pk_part, s| s << "#{model.table_name}.#{pk_part}" }
966
+ quoted_table_name = model.table_name.split('.').map { |x| "\"#{x}\"" }.join('.')
967
+ order = pk.each_with_object([]) { |pk_part, s| s << "#{quoted_table_name}.\"#{pk_part}\"" }
963
968
  ar_relation = order.present? ? model.order("#{order.join(', ')}") : model.all
964
969
  @_brick_params = ar_relation.brick_select(params, (selects = []), (bt_descrip = {}), (hm_counts = {}), (join_array = ::Brick::JoinArray.new))
965
970
  # %%% Add custom HM count columns
@@ -974,7 +979,8 @@ class Object
974
979
  @_brick_join_array = join_array
975
980
  end
976
981
 
977
- if model&.primary_key
982
+ is_pk_string = nil
983
+ if (pk_col = model&.primary_key)
978
984
  code << " def show\n"
979
985
  code << (find_by_id = " id = params[:id]&.split(/[\\/,_]/)
980
986
  id = id.first if id.is_a?(Array) && id.length == 1
@@ -982,7 +988,12 @@ class Object
982
988
  code << " end\n"
983
989
  self.define_method :show do
984
990
  ::Brick.set_db_schema(params)
985
- id = params[:id]&.split(/[\/,_]/)
991
+ id = if model.columns_hash[pk_col]&.type == :string
992
+ is_pk_string = true
993
+ params[:id]
994
+ else
995
+ params[:id]&.split(/[\/,_]/)
996
+ end
986
997
  id = id.first if id.is_a?(Array) && id.length == 1
987
998
  instance_variable_set("@#{singular_table_name}".to_sym, model.find(id))
988
999
  end
@@ -1021,7 +1032,7 @@ class Object
1021
1032
  # return
1022
1033
  end
1023
1034
 
1024
- id = params[:id]&.split(/[\/,_]/)
1035
+ id = is_pk_string ? params[:id] : params[:id]&.split(/[\/,_]/)
1025
1036
  id = id.first if id.is_a?(Array) && id.length == 1
1026
1037
  instance_variable_set("@#{singular_table_name}".to_sym, (obj = model.find(id)))
1027
1038
  obj = obj.first if obj.is_a?(Array)
@@ -1047,19 +1058,15 @@ class Object
1047
1058
  end
1048
1059
 
1049
1060
  def _brick_get_hm_assoc_name(relation, hm_assoc)
1050
- if relation[:hm_counts][hm_assoc[:assoc_name]]&.> 1
1051
- # binding.pry if (same_name = relation[:fks].find { |x| x.last[:assoc_name] == hm_assoc[:assoc_name] && x.last != hm_assoc }) #&&
1052
- # x.last[:alternate_name] == hm_assoc[:alternate_name] })
1053
- # relation[:fks].any? { |k, v| v[:assoc_name] == new_alt_name }
1061
+ if (relation[:hm_counts][hm_assoc[:assoc_name]]&.> 1) &&
1062
+ hm_assoc[:alternate_name] != hm_assoc[:inverse][:assoc_name]
1054
1063
  plural = ActiveSupport::Inflector.pluralize(hm_assoc[:alternate_name])
1055
- # binding.pry if hm_assoc[:assoc_name] == 'issue_issue_duplicates'
1056
1064
  new_alt_name = (hm_assoc[:alternate_name] == name.underscore) ? "#{hm_assoc[:assoc_name].singularize}_#{plural}" : plural
1057
1065
  # uniq = 1
1058
1066
  # while same_name = relation[:fks].find { |x| x.last[:assoc_name] == hm_assoc[:assoc_name] && x.last != hm_assoc }
1059
1067
  # hm_assoc[:assoc_name] = "#{hm_assoc_name}_#{uniq += 1}"
1060
1068
  # end
1061
1069
  # puts new_alt_name
1062
- # binding.pry if new_alt_name == 'issue_duplicates'
1063
1070
  # hm_assoc[:assoc_name] = new_alt_name
1064
1071
  [new_alt_name, true]
1065
1072
  else
@@ -1178,7 +1185,8 @@ module ActiveRecord::ConnectionHandling
1178
1185
  case ActiveRecord::Base.connection.adapter_name
1179
1186
  when 'PostgreSQL', 'SQLite' # These bring back a hash for each row because the query uses column aliases
1180
1187
  # schema ||= 'public' if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
1181
- ActiveRecord::Base.execute_sql(sql, ActiveRecord::Base.internal_metadata_table_name, ActiveRecord::Base.schema_migrations_table_name).each do |r|
1188
+ ar_imtn = ActiveRecord.version >= ::Gem::Version.new('5.0') ? ActiveRecord::Base.internal_metadata_table_name : ''
1189
+ ActiveRecord::Base.execute_sql(sql, ActiveRecord::Base.schema_migrations_table_name, ar_imtn).each do |r|
1182
1190
  # If Apartment gem lists the table as being associated with a non-tenanted model then use whatever it thinks
1183
1191
  # is the default schema, usually 'public'.
1184
1192
  schema_name = if ::Brick.config.schema_behavior[:multitenant]
@@ -1364,7 +1372,7 @@ module Brick
1364
1372
  is_schema = if ::Brick.config.schema_behavior[:multitenant]
1365
1373
  # If Apartment gem lists the primary table as being associated with a non-tenanted model
1366
1374
  # then use 'public' schema for the primary table
1367
- if apartment&.excluded_models.include?(fk[4].singularize.camelize)
1375
+ if apartment && apartment&.excluded_models.include?(fk[4].singularize.camelize)
1368
1376
  fk[3] = Apartment.default_schema
1369
1377
  true
1370
1378
  end
@@ -1446,7 +1454,6 @@ module Brick
1446
1454
  else
1447
1455
  fk[1]
1448
1456
  end
1449
- # binding.pry if inv_tbl == 'issue_issue_duplicates' # inverse_table goofed?
1450
1457
  assoc_hm = hms[hm_cnstr_name] = { is_bt: false, fk: fk[2], assoc_name: for_tbl.pluralize, alternate_name: bt_assoc_name,
1451
1458
  inverse_table: inv_tbl, inverse: assoc_bt }
1452
1459
  assoc_hm[:polymorphic] = true if is_polymorphic
@@ -216,12 +216,17 @@ input[type=submit] {
216
216
  <% def is_bcrypt?(val)
217
217
  val.is_a?(String) && val.length == 60 && val.start_with?('$2a$')
218
218
  end
219
- def hide_bcrypt(val)
219
+ def hide_bcrypt(val, max_len = 200)
220
220
  if is_bcrypt?(val)
221
221
  '(hidden)'
222
- elsif val.is_a?(String) && val.encoding.name != 'UTF-8'
223
- val[0..1000].force_encoding('UTF-8')
224
222
  else
223
+ if val.is_a?(String)
224
+ if val.length > max_len
225
+ val = val[0...max_len]
226
+ val << '...'
227
+ end
228
+ val.force_encoding('UTF-8') unless val.encoding.name == 'UTF-8'
229
+ end
225
230
  val
226
231
  end
227
232
  end %>"
@@ -250,40 +255,44 @@ end %>"
250
255
  var schemaSelect = document.getElementById(\"schema\");
251
256
  var tblSelect = document.getElementById(\"tbl\");
252
257
  var brickSchema;
253
- if (schemaSelect) {
254
- brickSchema = changeout(location.href, \"_brick_schema\");
255
- if (brickSchema) {
256
- [... document.getElementsByTagName(\"A\")].forEach(function (a) { a.href = changeout(a.href, \"_brick_schema\", brickSchema); });
258
+
259
+ // This PageTransitionEvent fires when the page first loads, as well as after any other history
260
+ // transition such as when using the browser's Back and Forward buttons.
261
+ window.addEventListener(\"pageshow\", function() {
262
+ if (schemaSelect) { // First drop-down is only present if multitenant
263
+ brickSchema = changeout(location.href, \"_brick_schema\");
264
+ if (brickSchema) {
265
+ [... document.getElementsByTagName(\"A\")].forEach(function (a) { a.href = changeout(a.href, \"_brick_schema\", brickSchema); });
266
+ }
267
+ schemaSelect.value = brickSchema || \"public\";
268
+ schemaSelect.focus();
269
+ schemaSelect.addEventListener(\"change\", function () {
270
+ // If there's an ID then remove it (trim after selected table)
271
+ location.href = changeout(location.href, \"_brick_schema\", this.value, tblSelect.value);
272
+ });
257
273
  }
258
- schemaSelect.value = brickSchema || \"public\";
259
- schemaSelect.focus();
260
- schemaSelect.addEventListener(\"change\", function () {
261
- // If there's an ID then remove it (trim after selected table)
262
- location.href = changeout(location.href, \"_brick_schema\", this.value, tblSelect.value);
263
- });
264
- }
265
- [... document.getElementsByTagName(\"FORM\")].forEach(function (form) {
266
- if (brickSchema)
267
- form.action = changeout(form.action, \"_brick_schema\", brickSchema);
268
- form.addEventListener('submit', function (ev) {
269
- [... ev.target.getElementsByTagName(\"SELECT\")].forEach(function (select) {
270
- if (select.value === \"^^^brick_NULL^^^\")
271
- select.value = null;
274
+ [... document.getElementsByTagName(\"FORM\")].forEach(function (form) {
275
+ if (brickSchema)
276
+ form.action = changeout(form.action, \"_brick_schema\", brickSchema);
277
+ form.addEventListener('submit', function (ev) {
278
+ [... ev.target.getElementsByTagName(\"SELECT\")].forEach(function (select) {
279
+ if (select.value === \"^^^brick_NULL^^^\")
280
+ select.value = null;
281
+ });
282
+ return true;
272
283
  });
273
- return true;
274
284
  });
275
- });
276
285
 
277
- if (tblSelect) {
278
- tblSelect.value = changeout(location.href)[0];
279
- if (tblSelect.selectedIndex < 0) tblSelect.value = changeout(location.href)[1];
280
- tblSelect.addEventListener(\"change\", function () {
281
- var lhr = changeout(location.href, null, this.value);
282
- if (brickSchema)
283
- lhr = changeout(lhr, \"_brick_schema\", schemaSelect.value);
284
- location.href = lhr;
285
- });
286
- }
286
+ if (tblSelect) { // Always present
287
+ tblSelect.value = changeout(location.href)[schemaSelect ? 1 : 0];
288
+ tblSelect.addEventListener(\"change\", function () {
289
+ var lhr = changeout(location.href, null, this.value);
290
+ if (brickSchema)
291
+ lhr = changeout(lhr, \"_brick_schema\", schemaSelect.value);
292
+ location.href = lhr;
293
+ });
294
+ }
295
+ });
287
296
 
288
297
  function changeout(href, param, value, trimAfter) {
289
298
  var hrefParts = href.split(\"?\");
@@ -366,7 +375,6 @@ function changeout(href, param, value, trimAfter) {
366
375
 
367
376
  async function updateSignInStatus(isSignedIn) {
368
377
  if (isSignedIn) {
369
- console.log(\"turds!\");
370
378
  await gapi.client.sheets.spreadsheets.create({
371
379
  properties: {
372
380
  title: #{table_name.inspect},
@@ -455,7 +463,6 @@ function changeout(href, param, value, trimAfter) {
455
463
  ::Brick.config.metadata_columns.include?(k) || poly_cols.include?(k) || k.start_with?('_brfk_') || (k.start_with?('_br_') && (k.length == 63 || k.end_with?('_ct'))) %>
456
464
  <td>
457
465
  <% if (bt = bts[k]) %>
458
- <%# binding.pry # Postgres column names are limited to 63 characters %>
459
466
  <% if bt[2] # Polymorphic?
460
467
  bt_class = #{obj_name}.send(\"#\{bt.first\}_type\")
461
468
  base_class = (::Brick.existing_stis[bt_class] || bt_class).constantize.base_class.name.underscore
@@ -464,6 +471,7 @@ function changeout(href, param, value, trimAfter) {
464
471
  send(\"#\{base_class\}_path\".to_sym, poly_id)) if poly_id %><%
465
472
  else
466
473
  bt_txt = (bt_class = bt[1].first.first).brick_descrip(
474
+ # 0..62 because Postgres column names are limited to 63 characters
467
475
  #{obj_name}, (descrips = @_brick_bt_descrip[bt.first][bt_class])[0..-2].map { |z| #{obj_name}.send(z.last[0..62]) }, (bt_id_col = descrips.last)
468
476
  )
469
477
  bt_id = #{obj_name}.send(*bt_id_col) if bt_id_col&.present? %>
@@ -546,7 +554,7 @@ function changeout(href, param, value, trimAfter) {
546
554
  <% else case #{model_name}.column_for_attribute(k).type
547
555
  when :string, :text %>
548
556
  <% if is_bcrypt?(val) # || .readonly? %>
549
- <%= hide_bcrypt(val) %>
557
+ <%= hide_bcrypt(val, 1000) %>
550
558
  <% else %>
551
559
  <div class=\"wide-input\"><%= f.text_field k.to_sym %></div>
552
560
  <% end %>
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 34
8
+ TINY = 35
9
9
 
10
10
  # PRE is nil unless it's a pre-release (beta, RC, etc.)
11
11
  PRE = nil
data/lib/brick.rb CHANGED
@@ -1,25 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_record/version'
4
-
5
- # ActiveRecord before 4.0 didn't have #version
6
- unless ActiveRecord.respond_to?(:version)
7
- module ActiveRecord
8
- def self.version
9
- ::Gem::Version.new(ActiveRecord::VERSION::STRING)
10
- end
11
- end
12
- end
13
-
14
- # In ActiveSupport older than 5.0, the duplicable? test tries to new up a BigDecimal,
15
- # and Ruby 2.6 and later deprecates #new. This removes the warning from BigDecimal.
16
- require 'bigdecimal'
17
- if (ruby_version = ::Gem::Version.new(RUBY_VERSION)) >= ::Gem::Version.new('2.6') &&
18
- ActiveRecord.version < ::Gem::Version.new('5.0')
19
- def BigDecimal.new(*args, **kwargs)
20
- BigDecimal(*args, **kwargs)
21
- end
22
- end
3
+ require 'brick/compatibility'
23
4
 
24
5
  # Allow ActiveRecord 4.0 and 4.1 to work with newer Ruby (>= 2.4) by avoiding a "stack level too deep"
25
6
  # error when ActiveSupport tries to smarten up Numeric by messing with Fixnum and Bignum at the end of:
@@ -45,8 +26,8 @@ end
45
26
  require 'brick/util'
46
27
 
47
28
  # Allow ActiveRecord < 3.2 to work with Ruby 2.7 and later
48
- if ActiveRecord.version < ::Gem::Version.new('3.2') &&
49
- ruby_version >= ::Gem::Version.new('2.7')
29
+ if (ruby_version = ::Gem::Version.new(RUBY_VERSION)) >= ::Gem::Version.new('2.7') &&
30
+ ActiveRecord.version < ::Gem::Version.new('3.2')
50
31
  # Remove circular reference for "now"
51
32
  ::Brick::Util._patch_require(
52
33
  'active_support/values/time_zone.rb', '/activesupport',
@@ -132,7 +113,6 @@ module Brick
132
113
  associatives = hms.each_with_object({}) do |hmt, s|
133
114
  if (through = hmt.last.options[:through])
134
115
  skip_hms[through] = nil
135
- # binding.pry if hmt.first == :issue_issues
136
116
  s[hmt.first] = hms[through] # End up with a hash of HMT names pointing to join-table associations
137
117
  elsif hmt.last.inverse_of.nil?
138
118
  puts "SKIPPING #{hmt.last.name.inspect}"
@@ -18,7 +18,8 @@ module Brick
18
18
  desc 'Generates an initializer file for configuring Brick'
19
19
 
20
20
  def create_initializer_file
21
- unless File.exist?(filename = 'config/initializers/brick.rb')
21
+ is_brick_file = File.exist?(filename = 'config/initializers/brick.rb')
22
+ if is_brick_file && ::Brick.config.schema_behavior[:multitenant] || !is_brick_file
22
23
  # See if we can make suggestions for additional_references and polymorphic associations
23
24
  resembles_fks = Hash.new { |h, k| h[k] = [] }
24
25
  possible_polymorphics = {}
@@ -223,7 +224,10 @@ module Brick
223
224
  # # Database schema to use when analysing existing data, such as deriving a list of polymorphic classes in the case that
224
225
  # # it wasn't originally specified.
225
226
  # Brick.schema_behavior = :namespaced
226
- # Brick.schema_behavior = { multitenant: { schema_to_analyse: 'engineering' } }
227
+ #{Brick.config.schema_behavior ? "Brick.schema_behavior = { multitenant: { schema_to_analyse: #{
228
+ Brick.config.schema_behavior[:multitenant][:schema_to_analyse].inspect}" :
229
+ "# Brick.schema_behavior = { multitenant: { schema_to_analyse: 'engineering'"
230
+ } } }
227
231
 
228
232
  # # Polymorphic associations are set up by providing a model name and polymorphic association name#{poly}
229
233
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brick
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.34
4
+ version: 1.0.35
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lorin Thwaits
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-06-23 00:00:00.000000000 Z
11
+ date: 2022-06-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -214,6 +214,7 @@ extensions: []
214
214
  extra_rdoc_files: []
215
215
  files:
216
216
  - lib/brick.rb
217
+ - lib/brick/compatibility.rb
217
218
  - lib/brick/config.rb
218
219
  - lib/brick/extensions.rb
219
220
  - lib/brick/frameworks/cucumber.rb