Skip to content

Commit 9403bf1

Browse files
committed
Add functionality to purge Object pollution from plain Ruby pipelines
- Set Ruby 3.1 as minimum version for the gem
1 parent eb9a1bd commit 9403bf1

File tree

8 files changed

+44
-4
lines changed

8 files changed

+44
-4
lines changed

.github/workflows/ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
runs-on: ubuntu-latest
1414
strategy:
1515
matrix:
16-
ruby_version: [2.7.2, 3.0.0, 3.2.0]
16+
ruby_version: [3.1.0, 3.2.0, 3.3.0]
1717
continue-on-error: ${{ endsWith(matrix.ruby, 'head') || matrix.ruby == 'debug' }}
1818
# Has to be top level to cache properly
1919
env:

.ruby-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.7.2
1+
3.1.4

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## 2.2.0
4+
5+
- Add functionality to purge certain `Object`-based method pollution which interferes with the workings of Serbea's `Pipeline` in pure Ruby.
6+
- Ruby 3.1 is now the minimum required version.
7+
38
## 2.1.0
49

510
- Remove Active Support as a dependency

docs/src/index.md

+4
Original file line numberDiff line numberDiff line change
@@ -392,3 +392,7 @@ Pipelines "inherit" their calling context by using Ruby's `binding` feature. Tha
392392
Another interesting facet of Serbea pipelines is that they're forgiving by default. If a filter can't be found (either there's no method available to call the object itself nor is there a separate helper method), it will log a warning to STDERR and continue on. This is to make the syntax feel a bit more like HTML and CSS where you can make a mistake or encounter an unexpected error condition yet not crash the entire application.
393393
394394
If you do want to crash your entire application (😜), you can set the configuration option: `Serbea::Pipeline.raise_on_missing_filters = true`. This will raise a `Serbea::FilterMissing` error if a filter can't be found.
395+
396+
**Note:** if you find that a certain method doesn't work within a pipeline when writing plain Ruby, because that method has polluted the global `Object` set of instance methods, you can call `Serbea::Pipeline.polluted_method(:method_name_here)` to strip that off and allow filtering to work. It also accepts an array of symbols.
397+
398+
**Note:** if you find that a certain filter is being called as a method directly on the value object, rather than a defined filter method itself, you can add that method name to a deny list via `Serbea::Pipeline.deny_value_method(:method_name_here)`. It also accepts an array of symbols.

lib/serbea/pipeline.rb

+20
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,27 @@ def self.value_methods_denylist
7272
@value_methods_denylist ||= Set.new
7373
end
7474

75+
def self.purge_class_pollution
76+
@pollution_purged ||= begin
77+
polluted_methods_list.each do |name|
78+
define_method name do |*args, **kwargs|
79+
filter(name, *args, **kwargs)
80+
end
81+
end
82+
83+
true
84+
end
85+
end
86+
87+
def self.polluted_method(name)
88+
polluted_methods_list.merge Array(name)
89+
end
90+
def self.polluted_methods_list
91+
@polluted_methods_list ||= Set.new(%i(select to_json))
92+
end
93+
7594
def initialize(binding, value)
95+
self.class.purge_class_pollution
7696
@binding = binding
7797
@context = binding.receiver
7898
@value = value

lib/version.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
module Serbea
2-
VERSION = "2.1.0"
2+
VERSION = "2.2.0"
33
end

serbea.gemspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
1111
spec.homepage = "https://github.com/bridgetownrb/serbea"
1212
spec.license = "MIT"
1313

14-
spec.required_ruby_version = ">= 2.7"
14+
spec.required_ruby_version = ">= 3.1"
1515

1616
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r!^(test|script|spec|features|docs|serbea-rails)/!) }
1717
spec.require_paths = ["lib"]

test/test.rb

+11
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,14 @@ def test_multiline(input_value)
246246
end
247247
end
248248

249+
def test_json_filter
250+
pipe({a: 1, b: "2"}) do
251+
select proc { _1 == :a }
252+
to_h
253+
to_json
254+
end
255+
end
256+
249257
def transform_this_way(input)
250258
input.join("=")
251259
end
@@ -267,4 +275,7 @@ def test_join(input, delimeter)
267275
raise "Multi-line pipeline broken! #{pipeline_output}" unless
268276
pipeline_output == "VAL A=123 !!"
269277

278+
pipeline_output = PipelineTemplateTest.new.test_json_filter
279+
raise "Unpolluted pipeline methods not working! #{pipeline_output}" unless pipeline_output == '{"a":1}'
280+
270281
puts "\nYay! Tests passed."

0 commit comments

Comments
 (0)