Reputation: 16084
I have a module:
module LiquidFilters
include ActionView::Helpers::AssetTagHelper
def stylesheet_tag(stylesheet_file_path)
stylesheet_link_tag stylesheet_file_path
end
end
And my spec:
describe LiquidFilters do
describe "#stylesheet_tag" do
it "should return the css file in an html (media=screen) tag" do
helper.stylesheet_tag("/path/css").should match(/<link href="\/path\/css\.css" media="screen" rel="stylesheet" type="text\/css"\s*\/>/)
end
end
end
But I get a wrong number of arguments (2 for 1) error:
Failures:
1) LiquidFilters#stylesheet_tag should return the css file in an html (media=screen) tag
Failure/Error: helper.stylesheet_tag("/path/css").should match(/<link href="\/path\/css\.css" media="screen" rel="stylesheet" type="text\/css"\s*\/>/)
wrong number of arguments (2 for 1)
# ./app/filters/liquid_filters.rb:16:in `stylesheet_tag'
# ./spec/helpers/liquid_filters_spec.rb:13
I can see the problem is at stylesheet_link_tag stylesheet_file_path
in the LiquidFilters
module -- the stylesheet_link_tag
is supposed to call a AssetTagHelper private method "stylesheet_tag", but it ends up calling LiquidFilter
's stylesheet_tag
method.
How do I force stylesheet_link_tag
to call AssetTagHelper
's methods, and not LiquidFilter
's?
Note: I'd like to keep the method name stylesheet_tag
.
Upvotes: 1
Views: 642
Reputation: 6068
Rails's alias_method_chain
could help:
module LiquidFilters
include ActionView::Helpers::AssetTagHelper
def stylesheet_tag_with_liquid(stylesheet_file_path, options = nil)
# if this got called with two arguments, proxy them to original
if options
stylesheet_tag_without_liquid(stylesheet_file_path, options)
else
stylesheet_link_tag stylesheet_file_path
end
end
def self.included(receiver)
alias_method_chain :stylesheet_tag, :liquid
end
end
While you still mask the original method, you can now proxy to it.
EDIT: moved alias_method_chain
to self.included
callback, so it won't be called before the module is actually included somewhere.
Upvotes: 0
Reputation: 9561
You could include the AssetTagHelper
module in a Helper
class to avoid the method name override, like this:
require 'singleton'
module LiquidFilters
class Helper
include Singleton
include ActionView::Helpers::AssetTagHelper
end
def stylesheet_tag(stylesheet_file_path)
Helper.instance.stylesheet_link_tag stylesheet_file_path
end
end
That way, your stylesheet_tag
method won't get mixed up with the AssetTagHelper
's private method.
Edit
Based on your feedback, I guess this is the closest you get then:
module LiquidFilters
include ActionView::Helpers::AssetTagHelper
alias :old_stylesheet_tag :stylesheet_tag
def stylesheet_tag(stylesheet_file_path, options = nil)
if options
old_stylesheet_tag(stylesheet_file_path, options)
else
stylesheet_link_tag stylesheet_file_path
end
end
end
You basically override the private method, so I don't think there is any other alternative than proxying calls.
Upvotes: 1