Skip to content

Commit

Permalink
Convert many Foundation extensions to refinements for cleaner monkeyp…
Browse files Browse the repository at this point in the history
…atching

- new .() and .with() features for Symbol
  • Loading branch information
jaredcwhite committed Apr 19, 2024
1 parent daf1908 commit 5163929
Show file tree
Hide file tree
Showing 20 changed files with 186 additions and 66 deletions.
2 changes: 2 additions & 0 deletions bridgetown-core/lib/bridgetown-core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ def to_liquid
class Rb < String; end

module Bridgetown
using Bridgetown::Refinements

autoload :Cache, "bridgetown-core/cache"
autoload :Current, "bridgetown-core/current"
autoload :Cleaner, "bridgetown-core/cleaner"
Expand Down
1 change: 1 addition & 0 deletions bridgetown-core/lib/bridgetown-core/collection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

module Bridgetown
class Collection
using Bridgetown::Refinements
include Enumerable

# @return [Bridgetown::Site]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
module Bridgetown
module Commands
module Actions
using Bridgetown::Refinements

GITHUB_REGEX = %r!https://github\.com!
GITHUB_TREE_REGEX = %r!#{GITHUB_REGEX}/.*/.*/tree/.*/?!
GITHUB_BLOB_REGEX = %r!#{GITHUB_REGEX}/.*/.*/blob/!
Expand Down
1 change: 1 addition & 0 deletions bridgetown-core/lib/bridgetown-core/commands/console.rb
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ def console # rubocop:disable Metrics
Bridgetown.logger.info "",
"You can also access #{"collections".cyan} or perform a " \
"#{"reload!".cyan}"
Bridgetown.logger.info "", "For extra Ruby smarts: #{"using Bridgetown::Refinements".cyan}"

trap("SIGINT") do
irb.signal_handle
Expand Down
3 changes: 2 additions & 1 deletion bridgetown-core/lib/bridgetown-core/component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

module Bridgetown
class Component
using Bridgetown::Refinements
include Bridgetown::Streamlined
extend Forwardable

Expand Down Expand Up @@ -120,7 +121,7 @@ def slot(name, input = nil, replace: false, &block)
content = block.nil? ? input.to_s : view_context.capture(&block)

name = name.to_s
slots.reject! { _1.name == name } if replace
slots.reject!(&:name.(:==, name)) if replace

slots << Slot.new(name:, content:, context: self, transform: false)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

class Bridgetown::Site
module FastRefreshable
using Bridgetown::Refinements

def fast_refresh(paths = [], reload_if_needed: false) # rubocop:todo Metrics
FileUtils.rm_f(Bridgetown.build_errors_path)

Expand Down Expand Up @@ -132,7 +134,7 @@ def mark_original_page_resources_for_fast_refresh(pages)
end

def transform_resources_for_fast_refresh(marked_resources, found_gen_pages)
marked_resources.each { _1.transform!.write }
marked_resources.each(&:transform!.(:write))
number_of_resources = marked_resources.length
number_of_resources += 1 if found_gen_pages
Bridgetown.logger.info(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
module Bridgetown
module Drops
class RelationsDrop < Drop
using Bridgetown::Refinements
mutable false

def [](type)
Expand Down
3 changes: 2 additions & 1 deletion bridgetown-core/lib/bridgetown-core/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
module Bridgetown
class RubyTemplateView
class Helpers
using Bridgetown::Refinements
include Bridgetown::Filters
include Bridgetown::Filters::FromLiquid
include ::Streamlined::Helpers
Expand Down Expand Up @@ -208,7 +209,7 @@ def slot(name, input = nil, replace: false, transform: true, &block)
end

name = name.to_s
resource.slots.reject! { _1.name == name } if replace
resource.slots.reject!(&:name.(:==, name)) if replace
resource.slots << Slot.new(
name:,
content:,
Expand Down
1 change: 1 addition & 0 deletions bridgetown-core/lib/bridgetown-core/model/repo_origin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
module Bridgetown
module Model
class RepoOrigin < Origin
using Bridgetown::Refinements
include Bridgetown::FrontMatter::Importer

# @return [String]
Expand Down
2 changes: 2 additions & 0 deletions bridgetown-core/lib/bridgetown-core/resource/relations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
module Bridgetown
module Resource
class Relations
using Bridgetown::Refinements

# @return [Bridgetown::Resource::Base]
attr_reader :resource

Expand Down
3 changes: 2 additions & 1 deletion bridgetown-core/lib/bridgetown-core/ruby_template_view.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def helper(name, &helper_block)
class RubyTemplateView
require "bridgetown-core/helpers"

using Bridgetown::Refinements
include Bridgetown::Streamlined

attr_reader :layout, :resource, :paginator, :site, :content
Expand Down Expand Up @@ -129,7 +130,7 @@ def _liquid_context
end

def _partial_path(partial_name, ext)
partial_name = partial_name.split("/").tap { _1.last.prepend("_") }.join("/")
partial_name = partial_name.split("/").tap(&:last.(:prepend, "_")).join("/")

# TODO: see if there's a workaround for this to speed up performance
site.in_source_dir(site.config[:partials_dir], "#{partial_name}.#{ext}")
Expand Down
4 changes: 3 additions & 1 deletion bridgetown-core/lib/bridgetown-core/slot.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

module Bridgetown
class Slot
using Bridgetown::Refinements

include Transformable

# @return [String]
Expand Down Expand Up @@ -33,7 +35,7 @@ def converters
context.transformer.send(:converters) :
context.send(:converters)

document_converters.select { _1.class.supports_slots? }
document_converters.select(&:class.(:supports_slots?))
end
end
end
50 changes: 50 additions & 0 deletions bridgetown-foundation/benchmark/refinements.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# frozen_string_literal: true

require "benchmark"

class TestInclusion
module StringAdder
def included_add(num)
to_i + num
end
end

String.include StringAdder

def self.perform
raise "crash!" unless "10".included_add(20) == 30
end
end

module StringAdderRefinement
refine String do
def refined_add(num)
to_i + num
end
end
end

class TestRefinement
using StringAdderRefinement

def self.perform
raise "crash!" unless "10".refined_add(20) == 30
end
end

raise "Unconfirmed!" unless "".respond_to?(:included_add)
raise "Unconfirmed!" if "".respond_to?(:refined_add)

n = 1_000_000
Benchmark.bmbm(12) do |x|
x.report("inclusion:") do
n.times do
TestInclusion.perform
end
end
x.report("refinements:") do
n.times do
TestRefinement.perform
end
end
end
44 changes: 19 additions & 25 deletions bridgetown-foundation/lib/bridgetown-foundation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,33 @@
require "bridgetown/foundation/version"
require "zeitwerk"

class Module
# Due to Active Support incompatibility, we can't extend Gem::Deprecate directly in `Object`
# So we're pulling this in as `gem_deprecate` from `deprecate`:
# https://github.com/rubygems/rubygems/blob/v3.5.9/lib/rubygems/deprecate.rb
#
# Pass in the deprecated method name, the new method name, and the year & month it'll be removed
module Bridgetown::Foundation
# This is loosly based on the `deprecate` method in `Gem::Deprecate`
#
# @param target [Object]
# @param name [Symbol] e.g. `:howdy`
# @param repl [Symbol] e.g. `:hello`
# @param year [Integer] e.g. `2025`
# @param month [Integer] e.g. `1` for January
def gem_deprecate(name, repl, year, month)
# rubocop:disable Style/FormatStringToken
class_eval do
old = "_deprecated_#{name}"
alias_method old, name
define_method name do |*args, &block|
klass = is_a? Module
target = klass ? "#{self}." : "#{self.class}#"
msg = [
"NOTE: #{target}#{name} is deprecated",
repl == :none ? " with no replacement" : "; use #{repl} instead",
format(". It will be removed on or after %4d-%02d.", year, month),
"\n#{target}#{name} called from #{Gem.location_of_caller.join(":")}",
]
warn "#{msg.join}." unless Gem::Deprecate.skip
send old, *args, &block
end
end
# rubocop:enable Style/FormatStringToken
def self.deprecation_warning(target, name, repl, year, month) # rubocop:disable Metrics/ParameterLists
klass = target.is_a?(Module)
target = klass ? "#{self}." : "#{self.class}#"
msg = [
"NOTE: #{target}#{name} is deprecated",
repl == :none ? " with no replacement" : "; use #{repl} instead",
format(". It will be removed on or after %4d-%02d.", year, month), # rubocop:disable Style/FormatStringToken
"\n#{target}#{name} called from #{Gem.location_of_caller.join(":")}",
]
warn "#{msg.join}."
end
end

# You can add `using Bridgetown::Refinements` to any portion of your Ruby code to load in all
# of the refinements available in Foundation. Or you can add a using statement for a particular
# refinement which lives inside `Bridgetown::Foundation::RefineExt`.
module Bridgetown::Refinements
end

Zeitwerk.with_loader do |l|
l.push_dir "#{__dir__}/bridgetown/foundation", namespace: Bridgetown::Foundation
l.ignore "#{__dir__}/bridgetown/foundation/version.rb"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,14 @@
module Bridgetown::Foundation
module CoreExt
module String
module Indentation
def indent!(indent_by, *args)
if args.length.positive?
Kernel.warn "multiple arguments aren't supported by `indent!' in Bridgetown", uplevel: 1
end

gsub! %r!^(?\!$)!, " " * indent_by
end

def indent(indent_by, *args)
if args.length.positive?
Kernel.warn "multiple arguments aren't supported by `indent' in Bridgetown", uplevel: 1
end

dup.indent!(indent_by)
end
end

module Questionable
def questionable = Bridgetown::Foundation::QuestionableString.new(self)
alias_method :inquiry, :questionable
gem_deprecate :inquiry, :questionable, 2024, 12
end

module StartsWithAndEndsWith
def self.included(klass)
klass.alias_method :starts_with?, :start_with?
klass.alias_method :ends_with?, :end_with?
end
end

::String.include Indentation, Questionable, StartsWithAndEndsWith
::String.include StartsWithAndEndsWith
end
end
end
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
# frozen_string_literal: true

module Bridgetown::Foundation
module CoreExt
module RefineExt
module Module
module Nested
using RefineExt::Object

refine ::Module do
def nested_within?(other)
other.nested_parents.within?(nested_parents[1..])
return false if self == other

other.nested_parents.within?(nested_parents) #[1..])
end

def nested_parents
Expand All @@ -25,8 +29,12 @@ def nested_name
name&.split("::")&.last
end
end

::Module.include Nested
end
end
end

module Bridgetown
module Refinements
include Foundation::RefineExt::Module
end
end
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# frozen_string_literal: true

module Bridgetown::Foundation
module CoreExt
module RefineExt
module Object
module WithinOther
refine ::Object do
# This method lets you check if the receiver is "within" the other object. In most cases,
# this check is accomplished via the `include?` method…aka, `10.within? [5, 10]` would
# return `true` as `[5, 10].include? 10` is true. And String/String comparison are
Expand Down Expand Up @@ -32,6 +32,8 @@ def within?(other) # rubocop:disable Metrics
end

if is_a?(Array) && other.is_a?(Array)
return false if empty?

return difference(other).empty?
end

Expand All @@ -51,11 +53,16 @@ def within?(other) # rubocop:disable Metrics

# NOTE: if you _really_ need to preserve Active Support's `in?` functionality, you can just
# require "active_support/core_ext/object/inclusion"
alias_method :in?, :within?
gem_deprecate :in?, :within?, 2024, 12
def in?(...) = Bridgetown::Foundation.deprecation_warning(
self, :in?, :within?, 2024, 12
).then { within?(...) }
end

::Object.include WithinOther
end
end
end

module Bridgetown
module Refinements
include Foundation::RefineExt::Object
end
end
Loading

0 comments on commit 5163929

Please sign in to comment.