From 2f921a0d430404549c0141a4e94b876e78b90455 Mon Sep 17 00:00:00 2001 From: Jorge Garcia Date: Fri, 20 Jun 2025 15:20:29 -0600 Subject: [PATCH 1/9] Fix rubocop offenses on Definition --- lib/slither/definition.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/slither/definition.rb b/lib/slither/definition.rb index adb0e07..6414659 100644 --- a/lib/slither/definition.rb +++ b/lib/slither/definition.rb @@ -76,8 +76,8 @@ def template(name, options = {}, &block) # @param block [Block] A block for defining fields within the section. # @return [Section] The newly created section. # - def method_missing(method, *args, &block) # rubocop:disable Style/MissingRespondToMissing - section(method, *args, &block) + def method_missing(method, *, &block) # rubocop:disable Style/MissingRespondToMissing + section(method, *, &block) end private From ddaa1ca57ed8dabe573dffd3ba8b35c5842846fc Mon Sep 17 00:00:00 2001 From: Jorge Garcia Date: Fri, 20 Jun 2025 16:18:04 -0600 Subject: [PATCH 2/9] Test: add method_missing direct expectation --- lib/slither/section.rb | 2 +- spec/slither/section_spec.rb | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/slither/section.rb b/lib/slither/section.rb index 3b82aaa..b609dae 100644 --- a/lib/slither/section.rb +++ b/lib/slither/section.rb @@ -88,7 +88,7 @@ def method_missing(method, *args) private def unpacker - @columns.map { |c| c.unpacker }.join('') + @columns.map(&:unpacker).join end end end diff --git a/spec/slither/section_spec.rb b/spec/slither/section_spec.rb index b288505..79bbb10 100644 --- a/spec/slither/section_spec.rb +++ b/spec/slither/section_spec.rb @@ -59,6 +59,7 @@ context "when using a method that's not defined" do it "uses method_missing to create a column" do + expect(subject).to receive(:method_missing).and_call_original column = subject.first_name(5) expect(subject.columns).to match([column]) From 86855fdeb6c0bb3c0ebc8e59d4c42f7940a1d13c Mon Sep 17 00:00:00 2001 From: Jorge Garcia Date: Fri, 20 Jun 2025 16:19:34 -0600 Subject: [PATCH 3/9] Fix: method_missing Section offenses --- lib/slither/section.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/slither/section.rb b/lib/slither/section.rb index b609dae..5331072 100644 --- a/lib/slither/section.rb +++ b/lib/slither/section.rb @@ -81,8 +81,12 @@ def match(raw_line) raw_line.nil? ? false : @trap.call(raw_line) end - def method_missing(method, *args) - column(method, *args) + def respond_to_missing?(_method_name, _include_private = false) + true + end + + def method_missing(method, *) + column(method, *) end private From 2392d21d7955774b9b4f55242545ab6fd3d29dc7 Mon Sep 17 00:00:00 2001 From: Jorge Garcia Date: Fri, 20 Jun 2025 16:20:57 -0600 Subject: [PATCH 4/9] Fix: Section change single strings to doubles --- lib/slither/section.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/slither/section.rb b/lib/slither/section.rb index 5331072..091bca0 100644 --- a/lib/slither/section.rb +++ b/lib/slither/section.rb @@ -52,10 +52,12 @@ def format(data) # raise( ColumnMismatchError, # "The '#{@name}' section has #{@columns.size} column(s) defined, but there are #{data.size} column(s) provided in the data." # ) unless @columns.size == data.size - row = '' + row = "" + @columns.each do |column| row += column.format(data[column.name]) end + row end @@ -70,10 +72,12 @@ def parse(line) def parse_when_problem(line) line_data = line.unpack(@columns.map { |c| "a#{c.length}" }.join('')) - row = '' + row = "" + @columns.each_with_index do |c, i| row << "\n'#{c.name}':'#{line_data[i]}'" unless RESERVED_NAMES.include?(c.name) end + row end From 804b6d9ff4a09fe69425203364375acc9b8fe67d Mon Sep 17 00:00:00 2001 From: Jorge Garcia Date: Fri, 20 Jun 2025 16:22:17 -0600 Subject: [PATCH 5/9] Fix: Freeze reserved names Array --- lib/slither/section.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/slither/section.rb b/lib/slither/section.rb index 091bca0..efca54a 100644 --- a/lib/slither/section.rb +++ b/lib/slither/section.rb @@ -3,7 +3,7 @@ class Section attr_accessor :definition, :optional attr_reader :name, :columns, :options, :length - RESERVED_NAMES = [:spacer] + RESERVED_NAMES = [:spacer].freeze def initialize(name, options = {}) @name = name From 5ee0ec78f41d2ab70dc87de0957ea0d75b9ba2d7 Mon Sep 17 00:00:00 2001 From: Jorge Garcia Date: Fri, 20 Jun 2025 16:23:05 -0600 Subject: [PATCH 6/9] Fix: Section add line break after raise --- lib/slither/section.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/slither/section.rb b/lib/slither/section.rb index efca54a..68b1b1e 100644 --- a/lib/slither/section.rb +++ b/lib/slither/section.rb @@ -35,6 +35,7 @@ def trap(&block) def template(name) template = @definition.templates[name] raise ArgumentError, "Template #{name} not found as a known template." unless template + @columns += template.columns @length += template.length # Section options should trump template options From 911a0be29e0f626ffb991218658dc727e5c61a47 Mon Sep 17 00:00:00 2001 From: Jorge Garcia Date: Fri, 20 Jun 2025 16:25:41 -0600 Subject: [PATCH 7/9] Fix: regenerate Section file --- lib/slither/section.rb | 206 ++++++++++++++++++++--------------------- 1 file changed, 103 insertions(+), 103 deletions(-) diff --git a/lib/slither/section.rb b/lib/slither/section.rb index 68b1b1e..2d71968 100644 --- a/lib/slither/section.rb +++ b/lib/slither/section.rb @@ -1,103 +1,103 @@ -module Slither - class Section - attr_accessor :definition, :optional - attr_reader :name, :columns, :options, :length - - RESERVED_NAMES = [:spacer].freeze - - def initialize(name, options = {}) - @name = name - @options = options - @columns = [] - @trap = options[:trap] - @optional = options[:optional] || false - @length = 0 - end - - def column(name, length, options = {}) - raise(Slither::DuplicateColumnNameError, "You have already defined a column named '#{name}'.") if @columns.map do |c| - RESERVED_NAMES.include?(c.name) ? nil : c.name - end.flatten.include?(name) - col = Column.new(name, length, @options.merge(options)) - @columns << col - @length += length - col - end - - def spacer(length) - column(:spacer, length) - end - - def trap(&block) - @trap = block - end - - def template(name) - template = @definition.templates[name] - raise ArgumentError, "Template #{name} not found as a known template." unless template - - @columns += template.columns - @length += template.length - # Section options should trump template options - @options = template.options.merge(@options) - end - - # Format a data Hash using columns width. - # - Data - hash, based on columns definitions content. - # Ex: Having the next 2 columns .column(:id, 5) && .column(:name, 10) - # we pass the data hash data = { id: 3, name: "Ryan" } - # the result is the content of the hash based on the columns width: - # format(data) - # => " 3 Ryan" - def format(data) - # raise( ColumnMismatchError, - # "The '#{@name}' section has #{@columns.size} column(s) defined, but there are #{data.size} column(s) provided in the data." - # ) unless @columns.size == data.size - row = "" - - @columns.each do |column| - row += column.format(data[column.name]) - end - - row - end - - def parse(line) - line_data = line.unpack(unpacker) - row = {} - @columns.each_with_index do |c, i| - row[c.name] = c.parse(line_data[i]) unless RESERVED_NAMES.include?(c.name) - end - row - end - - def parse_when_problem(line) - line_data = line.unpack(@columns.map { |c| "a#{c.length}" }.join('')) - row = "" - - @columns.each_with_index do |c, i| - row << "\n'#{c.name}':'#{line_data[i]}'" unless RESERVED_NAMES.include?(c.name) - end - - row - end - - def match(raw_line) - raw_line.nil? ? false : @trap.call(raw_line) - end - - def respond_to_missing?(_method_name, _include_private = false) - true - end - - def method_missing(method, *) - column(method, *) - end - - private - - def unpacker - @columns.map(&:unpacker).join - end - end -end +module Slither + class Section + attr_accessor :definition, :optional + attr_reader :name, :columns, :options, :length + + RESERVED_NAMES = [:spacer].freeze + + def initialize(name, options = {}) + @name = name + @options = options + @columns = [] + @trap = options[:trap] + @optional = options[:optional] || false + @length = 0 + end + + def column(name, length, options = {}) + raise(Slither::DuplicateColumnNameError, "You have already defined a column named '#{name}'.") if @columns.map do |c| + RESERVED_NAMES.include?(c.name) ? nil : c.name + end.flatten.include?(name) + col = Column.new(name, length, @options.merge(options)) + @columns << col + @length += length + col + end + + def spacer(length) + column(:spacer, length) + end + + def trap(&block) + @trap = block + end + + def template(name) + template = @definition.templates[name] + raise ArgumentError, "Template #{name} not found as a known template." unless template + + @columns += template.columns + @length += template.length + # Section options should trump template options + @options = template.options.merge(@options) + end + + # Format a data Hash using columns width. + # - Data - hash, based on columns definitions content. + # Ex: Having the next 2 columns .column(:id, 5) && .column(:name, 10) + # we pass the data hash data = { id: 3, name: "Ryan" } + # the result is the content of the hash based on the columns width: + # format(data) + # => " 3 Ryan" + def format(data) + # raise( ColumnMismatchError, + # "The '#{@name}' section has #{@columns.size} column(s) defined, but there are #{data.size} column(s) provided in the data." + # ) unless @columns.size == data.size + row = "" + + @columns.each do |column| + row += column.format(data[column.name]) + end + + row + end + + def parse(line) + line_data = line.unpack(unpacker) + row = {} + @columns.each_with_index do |c, i| + row[c.name] = c.parse(line_data[i]) unless RESERVED_NAMES.include?(c.name) + end + row + end + + def parse_when_problem(line) + line_data = line.unpack(@columns.map { |c| "a#{c.length}" }.join('')) + row = "" + + @columns.each_with_index do |c, i| + row << "\n'#{c.name}':'#{line_data[i]}'" unless RESERVED_NAMES.include?(c.name) + end + + row + end + + def match(raw_line) + raw_line.nil? ? false : @trap.call(raw_line) + end + + def respond_to_missing?(_method_name, _include_private = false) + true + end + + def method_missing(method, *) + column(method, *) + end + + private + + def unpacker + @columns.map(&:unpacker).join + end + end +end From 3b07dce1b737bb80f6cb951cadd78d79be0c218f Mon Sep 17 00:00:00 2001 From: Jorge Garcia Date: Fri, 20 Jun 2025 16:28:29 -0600 Subject: [PATCH 8/9] Fix: add magic comment & change Strings mutations to support it --- lib/slither/section.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/slither/section.rb b/lib/slither/section.rb index 2d71968..5a6b97c 100644 --- a/lib/slither/section.rb +++ b/lib/slither/section.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Slither class Section attr_accessor :definition, :optional @@ -53,7 +55,7 @@ def format(data) # raise( ColumnMismatchError, # "The '#{@name}' section has #{@columns.size} column(s) defined, but there are #{data.size} column(s) provided in the data." # ) unless @columns.size == data.size - row = "" + row = String.new @columns.each do |column| row += column.format(data[column.name]) @@ -73,7 +75,7 @@ def parse(line) def parse_when_problem(line) line_data = line.unpack(@columns.map { |c| "a#{c.length}" }.join('')) - row = "" + row = String.new @columns.each_with_index do |c, i| row << "\n'#{c.name}':'#{line_data[i]}'" unless RESERVED_NAMES.include?(c.name) From 0d4bbb36b32fbcf053bbf31c39dd4e2bc0f6dcf8 Mon Sep 17 00:00:00 2001 From: Jorge Garcia Date: Fri, 20 Jun 2025 16:30:32 -0600 Subject: [PATCH 9/9] Fix: re-do dup checks to comply with Rubocop --- lib/slither/section.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/slither/section.rb b/lib/slither/section.rb index 5a6b97c..e40c689 100644 --- a/lib/slither/section.rb +++ b/lib/slither/section.rb @@ -17,9 +17,13 @@ def initialize(name, options = {}) end def column(name, length, options = {}) - raise(Slither::DuplicateColumnNameError, "You have already defined a column named '#{name}'.") if @columns.map do |c| + if @columns.map do |c| RESERVED_NAMES.include?(c.name) ? nil : c.name end.flatten.include?(name) + raise(Slither::DuplicateColumnNameError, + "You have already defined a column named '#{name}'.") + end + col = Column.new(name, length, @options.merge(options)) @columns << col @length += length @@ -74,7 +78,7 @@ def parse(line) end def parse_when_problem(line) - line_data = line.unpack(@columns.map { |c| "a#{c.length}" }.join('')) + line_data = line.unpack(@columns.map { |c| "a#{c.length}" }.join) row = String.new @columns.each_with_index do |c, i|