In Ruby, how can I refer to a lambda that is defined in a module?
This code was used until I included my lambda function in the module.
Here is the lambda function:
module GalleryGenerator
@add_links_to_descriptions = lambda do |mutable_viewable_content|
mutable_viewable_content.description = add_links_to_sources(mutable_viewable_content.description)
return mutable_viewable_content
end
#...
end
This is how it is used:
include GalleryGenerator
gallery = ViewableGallery.new(gallery_config.title, gallery_config.description, gallery_config.slug, \
gallery_config.sources, gallery_config.upload_date, gallery_config.map_url, gallery_config.map_title, \
gallery_config.year, viewable_photos).
update_using( \
add_tabs_before_every_description_line(2), \
@add_links_to_descriptions)
What's the error:
/home/mike/Development/Projects/FT/gallery_generator/lib/gallery_generator/viewable_gallery.rb:26:in `block in update_using': undefined method `call' for nil:NilClass (NoMethodError)
from /home/mike/Development/Projects/FT/gallery_generator/lib/gallery_generator/viewable_gallery.rb:25:in `each'
from /home/mike/Development/Projects/FT/gallery_generator/lib/gallery_generator/viewable_gallery.rb:25:in `update_using'
from bin/gallery_generator:32:in `<main>'
If the lambda message is not in the module everything works. I suspect it is looking for @add_links_to_descriptions in the wrong place now that in a module ...
How can I fix this? Thank!
source to share
try this:
module GalleryGenerator
def self.add_links_to_descriptions
lambda do |mutable_viewable_content|
mutable_viewable_content.description = add_links_to_sources(mutable_viewable_content.description)
return mutable_viewable_content
end
end
#...
end
and call it GalleryGenerator.add_links_to_descriptions
source to share
In Ruby, variables that start with a symbol @
are instance variables, that is, variables that belong to a particular object (or instance).
In this case, the instance variable @add_links_to_descriptions
belongs to the object referenced by the constant GalleryGenerator
and can only be accessed by one object.
The only things available to other objects in Ruby are methods. So, you need to define a method that returns the value of an instance variable. Such a method is called an attribute reader in Ruby, and there is a convenient method for generating them automatically called Module#attr_reader
:
class << GalleryGenerator
attr_reader :add_links_to_descriptions
end
class Foo
GalleryGenerator.add_links_to_descriptions.(nil)
end
Alternatively, you can use a constant instead of an instance variable. Constants are capitalized:
module GalleryGenerator
AddLinksToDescriptions = -> mutable_viewable_content {
mutable_viewable_content.tap do |m|
m.description = add_links_to_sources(m.description)
end
}
end
class Foo
GalleryGenerator::AddLinksToDescriptions.(nil)
end
Or you use the cold version of the class hierarchy variable (denoted by a symbol @@
):
module GalleryGenerator
@@add_links_to_descriptions = -> mutable_viewable_content {
mutable_viewable_content.tap do |m|
m.description = add_links_to_sources(m.description)
end
}
end
class Foo
include GalleryGenerator
@@add_links_to_descriptions.(nil)
end
source to share
Just make lambda
a constant or instance method that returns a lambda.
module GalleryGenerator
LINKS_TO_DESCRIPTION_ADDER = lambda do |mutable_viewable_content|
mutable_viewable_content.description = add_links_to_sources(mutable_viewable_content.description)
return mutable_viewable_content
end
#...
end
update_using( \
add_tabs_before_every_description_line(2), \
LINKS_TO_DESCRIPTION_ADDER)
source to share