In this episode, we're going behind-the-scenes rails ActiveSupport
module. And see how a few of the common methods are implemented. In doing so, we'll see examples of ruby metaprogramming concepts in practice.
[Format: flip between rails console session and the rails source code to demonstrate each method]
Open Class
squish
andsquish!
source code https://github.com/rails/rails/blob/v7.0.8/activesupport/lib/active_support/core_ext/string/filters.rb
blank?
andpresent?
It opens so many classes to get the desired behavior.Object
,NilClass
,FalseClass
,TrueClass
,Array
,Hash
,String
,Numric
,Time
But the end of the day is using empty?
(the string part is bit more involved)
sourcecode https://github.com/rails/rails/blob/v7.0.8/activesupport/lib/active_support/core_ext/object/blank.rb
Method Missing
3. inquiry
and StringInquirer
- demonstrate method_missing and respond_to_missing
class StringInquirer < String
private
def respond_to_missing?(method_name, include_private = false)
method_name.end_with?("?") || super
end
def method_missing(method_name, *arguments)
if method_name.end_with?("?")
self == method_name[0..-2]
else
super
end
end
end
For StringInquirer
:
The sourcecode https://github.com/rails/rails/blob/832fb1de704899a230c83e7c966efac03a012137/activesupport/lib/active_support/string_inquirer.rb#L21
Using it in Rails.env https://github.com/rails/rails/blob/832fb1de704899a230c83e7c966efac03a012137/railties/lib/rails.rb#L72
It uses a subclass of StringInquirer called EnvironmentInquirer that does not rely on method_missing. uses instance_variable_set
, class_eval
https://github.com/rails/rails/blob/main/activesupport/lib/active_support/environment_inquirer.rb#L7
An aside - bunch of methods in ActiveSupport
are simply an alias for existing ruby methods. starts_with?
and ends_with?
in both String
and Symbol
for example [not sure if worth mentioning this. alias
is a keyword in Ruby and doesn't really have anything to do with metaprogramming]
Bonus
ActiveSupport::Inflector
[I found this class interesting. Not sure if it will fit in this screencast. Likely a separate episode, not mix too many things]
One example is constantize
which is simply doing Object.const_get
since all Class and Module names are constants in Ruby.