Skip to content

Commit

Permalink
Refactor builder DSL for Ruby 2.7 & 3.0 compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
jaredcwhite committed Nov 5, 2021
1 parent 9f9c4f1 commit 10ce301
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 32 deletions.
18 changes: 12 additions & 6 deletions bridgetown-builder/lib/bridgetown-builder/dsl/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,19 @@ def helper(helper_name, method_name = nil, helpers_scope: false, &block)
builder_self = self
m = Module.new

if block && !helpers_scope
m.define_method helper_name do |*args|
builder_self.instance_exec(*args, &block)
end
else
block = method(method_name) if method_name
if block && helpers_scope
m.define_method helper_name, &block
else
method_name ||= helper_name unless block
unless method_name
method_name = :"__helper_#{helper_name}"
builder_self.define_singleton_method(method_name) do |*args, **kwargs, &block2|
block.(*args, **kwargs, &block2)
end
end
m.define_method helper_name do |*args, **kwargs, &block2|
builder_self.send(method_name, *args, **kwargs, &block2)
end
end

Bridgetown::RubyTemplateView::Helpers.include(m)
Expand Down
21 changes: 14 additions & 7 deletions bridgetown-builder/lib/bridgetown-builder/dsl/liquid.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,19 @@ def liquid_filter(filter_name, method_name = nil, filters_scope: false, &block)
builder_self = self
m = Module.new

if block && !filters_scope
m.define_method filter_name do |*args|
builder_self.instance_exec(*args, &block)
end
else
block = method(method_name) if method_name
if block && filters_scope
m.define_method filter_name, &block
else
method_name ||= filter_name unless block
unless method_name
method_name = :"__filter_#{filter_name}"
builder_self.define_singleton_method(method_name) do |*args, **kwargs|
block.(*args, **kwargs) # rubocop:disable Performance/RedundantBlockCall
end
end
m.define_method filter_name do |*args, **kwargs|
builder_self.send(method_name, *args, **kwargs)
end
end

::Liquid::Template.register_filter(m)
Expand All @@ -23,7 +29,8 @@ def liquid_filter(filter_name, method_name = nil, filters_scope: false, &block)
end

def liquid_tag(tag_name, method_name = nil, as_block: false, &block)
block = method(method_name) if method_name.is_a?(Symbol)
method_name ||= tag_name unless block
block = method(method_name) if method_name
local_name = name # pull the name method into a local variable

tag_class = as_block ? ::Liquid::Block : ::Liquid::Tag
Expand Down
2 changes: 1 addition & 1 deletion bridgetown-builder/test/test_filters_dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

class FiltersBuilder < Builder
def build
liquid_filter "multiply_by_2" do |input|
liquid_filter :multiply_by_2 do |input|
input * 2
end

Expand Down
4 changes: 2 additions & 2 deletions bridgetown-builder/test/test_helpers_dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@

class HelpersBuilder < Builder
def build
helper "block_based" do |something|
helper :block_based do |something|
"Block Based #{something} #{self.class}"
end

helper "within_helpers_scope", helpers_scope: true do |something|
"Within Helpers Scope Based #{something} #{self.class} #{slugify("I Am Groot")} #{view.class} #{site.class}"
end

helper "method_based", :method_based
helper :method_based
end

def method_based(something)
Expand Down
2 changes: 1 addition & 1 deletion bridgetown-builder/test/test_method_symbols.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
class MethodSymbolsBuilder < Builder
def build
generator :set_title
liquid_tag "upcase_tag", :upcase_tag, as_block: true
liquid_tag :upcase_tag, as_block: true
liquid_filter "multiply_by_anything", :multiply_filter
hook :site, :after_reset, :reset_hook
end
Expand Down
2 changes: 1 addition & 1 deletion bridgetown-builder/test/test_tags_dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def build
"output of the tag #{attr}"
end

liquid_tag "upcase_tag", as_block: true do |_attributes, tag|
liquid_tag :upcase_tag, as_block: true do |_attributes, tag|
tag.content.upcase
end

Expand Down
4 changes: 2 additions & 2 deletions bridgetown-core/lib/bridgetown-core/plugin_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ def self.add_source_manifest(source_manifest)
@source_manifests << source_manifest
end

def self.new_source_manifest(*args)
add_source_manifest(Bridgetown::Plugin::SourceManifest.new(*args))
def self.new_source_manifest(*args, **kwargs)
add_source_manifest(Bridgetown::Plugin::SourceManifest.new(*args, **kwargs))
end

def self.add_registered_plugin(gem_or_plugin_file)
Expand Down
10 changes: 6 additions & 4 deletions bridgetown-website/src/_docs/plugins/filters.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Example:
```ruby
class Filters < SiteBuilder
def build
liquid_filter "cache_busting_url" do |url|
liquid_filter :cache_busting_url do |url|
"http://www.example.com/#{url}?#{Time.now.to_i}"
end
end
Expand All @@ -39,7 +39,7 @@ You can accept multiple arguments to your filter by simply adding them to your b
```ruby
class Filters < SiteBuilder
def build
liquid_filter "multiply_and_optionally_add" do |input, multiply_by, add_by = nil|
liquid_filter :multiply_and_optionally_add do |input, multiply_by, add_by = nil|
value = input * multiply_by
add_by ? value + add_by : value
end
Expand Down Expand Up @@ -78,7 +78,7 @@ As with other parts of the Builder API, you can also use an instance method to r
```ruby
class Filters < SiteBuilder
def build
liquid_filter "cache_busting_url", :bust_it
liquid_filter :cache_busting_url, :bust_it
end

def bust_it(url)
Expand All @@ -87,6 +87,8 @@ class Filters < SiteBuilder
end
```

If your filter name and method name are the same, you can omit the second argument.

## Filter Execution Scope

By default, the code within the filter block or method is executed within the scope of the builder object. This means you will not have access to other filters you may expecting to call. For example, if you want to call `slugify` from your filter, it will cause an error.
Expand All @@ -96,7 +98,7 @@ To remedy this, simply pass the `filters_scope: true` argument when defining a f
```ruby
class Filters < SiteBuilder
def build
liquid_filter "slugify_and_upcase", filters_scope: true do |url|
liquid_filter :slugify_and_upcase, filters_scope: true do |url|
slugify(url).upcase
end
end
Expand Down
12 changes: 7 additions & 5 deletions bridgetown-website/src/_docs/plugins/helpers.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Example:
```ruby
class Helpers < SiteBuilder
def build
helper "cache_busting_url" do |url|
helper :cache_busting_url do |url|
"http://www.example.com/#{url}?#{Time.now.to_i}"
end
end
Expand All @@ -36,7 +36,7 @@ You can accept multiple arguments to your helper by simply adding them to your b
```ruby
class Helpers < SiteBuilder
def build
helper "multiply_and_optionally_add" do |input, multiply_by, add_by = nil|
helper :multiply_and_optionally_add do |input, multiply_by, add_by = nil|
value = input * multiply_by
add_by ? value + add_by : value
end
Expand All @@ -63,7 +63,7 @@ As with other parts of the Builder API, you can also use an instance method to r
```ruby
class Helpers < SiteBuilder
def build
helper "cache_busting_url", :bust_it
helper :cache_busting_url, :bust_it
end

def bust_it(url)
Expand All @@ -72,6 +72,8 @@ class Helpers < SiteBuilder
end
```

If your helper name and method name are the same, you can omit the second argument.

## Helper Execution Scope

By default, the code within the helper block or method is executed within the scope of the builder object. This means you will not have access to other helpers you may expecting to call. For example, if you want to call `slugify` from your helper, it will cause an error.
Expand All @@ -81,7 +83,7 @@ To remedy this, simply pass the `helpers_scope: true` argument when defining a h
```ruby
class Helpers < SiteBuilder
def build
helper "slugify_and_upcase", helpers_scope: true do |url|
helper :slugify_and_upcase, helpers_scope: true do |url|
slugify(url).upcase
end
end
Expand All @@ -97,7 +99,7 @@ Within the helpers scope, you can "capture" the contents of a block and use that
```ruby
class Helpers < SiteBuilder
def build
helper "capture_and_upcase", helpers_scope: true do |&block|
helper :capture_and_upcase, helpers_scope: true do |&block|
label = "upcased"
view.capture(label, &block).upcase
end
Expand Down
8 changes: 5 additions & 3 deletions bridgetown-website/src/_docs/plugins/tags.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ will output the time the page was rendered:
```ruby
class RenderTime < SiteBuilder
def build
liquid_tag "render_time" do |attributes|
liquid_tag :render_time do |attributes|
"#{attributes} #{Time.now}"
end
end
Expand Down Expand Up @@ -43,7 +43,7 @@ The `render_time` tag seen above can also be rewritten as a _tag block_. Look at
```ruby
class RenderTime < SiteBuilder
def build
liquid_tag "render_time", as_block: true do |attributes, tag|
liquid_tag :render_time, as_block: true do |attributes, tag|
"#{tag.content} #{Time.now}"
end
end
Expand Down Expand Up @@ -78,7 +78,7 @@ As with other parts of the Builder API, you can also use an instance method to r
```ruby
class Upcase < SiteBuilder
def build
liquid_tag "upcase", :upcase_tag, as_block: true
liquid_tag :upcase, :upcase_tag, as_block: true
end

def upcase_tag(attributes, tag)
Expand All @@ -87,6 +87,8 @@ class Upcase < SiteBuilder
end
```

If your tag name and method name are the same, you can omit the second argument.

{% raw %}
```liquid
{% upcase %}
Expand Down

0 comments on commit 10ce301

Please sign in to comment.