Ruby will not recognize Diet module, will recognize Diets module - ruby

I have a main file, simple_carbon_calculator.rb, that requires a number of different files, but namely diet.rb. Both files require a data file, constants_and_converesions.rb.
In simple_carbon_calculator.rb:
require_relative 'constanst_and_conversions.rb'
require_relative 'diet.rb'
# Other Code
Diet.get_diet_emissions
In diet.rb:
require_relative 'constants_and_conversions.rb'
module Diet
def self.get_diet_emissions
## function
end
end
When I run simple_carbon_calculator.rb, the TypeError is raised: "Diet is not a module" However, when I change the module to be named Diets (note the s), it works fine. I honestly have no idea why. Any thoughts?
Cheers and thanks,
Reid

Related

Monkey-patch using modules in a gem

I'm building a Ruby gem that includes a module that's meant to monkey-patch the Hash class to add a new method. I'm following this guide to try to do it neatly: http://www.justinweiss.com/articles/3-ways-to-monkey-patch-without-making-a-mess/
I've placed the module in lib/core_extensions/hash/prune.rb, and the module is declared as such:
module CoreExtensions
module Hash
module Prune
##
# Removes all pairs from the Hash for which the value is nil. Destructive!
def prune!
self.reject! { |_, v| v.nil? }
end
end
end
end
And in order to make the monkey patch take effect, I'm calling this within the main gem file:
Hash.include(CoreExtensions::Hash::Prune)
But after building the gem and trying to require it in an irb console, I get the following error: NameError: uninitialized constant Gem::CoreExtensions (Gem is a placeholder name).
I made sure to include the prune.rb file in my gemspec's files array: s.files = ['lib/gem.rb', 'lib/core_extensions/hash/prune.rb'], so I'm not sure why it can't detect the file and its modules. Can anyone help me figure this out?
Thank you!
EDIT: In case it will help anyone else - I tried to require the module file using require 'lib/core_extensions/hash/prune' but received 'cannot load such file' errors. Sticking ./ in front of the path fixed it.

Load Error in require statement when using classes in multiple files

I'm pretty new to Ruby and facing a pretty basic problem i guess. I'm probably missing out on some basic concepts and constructs. So this is what i'm trying to do,
I'm writing a sinatra project, and i have a classes which are written in different files. The structure looks something of this sort,
project_name
- api.rb
- base.rb
- settings.rb
In my api.rb file i have defined a class and some methods, it also calls some methods form base.rb and base.rb calls some methods from settings.rb
In api.rb
require 'sinatra'
require 'json'
require 'uri'
require 'base' --> This is the base.rb which is resulting in error
module XX
class Api
def some_method
base = Base.new
base.setup
# some more code
end
end
end
In base.rb, it has the following code
require 'settings'
module XX
class Base
def setup
# some code
end
def some_method
#some code
end
end
end
When i just run ruby api.rb, i'm getting an error in the require statement, unable to load such file-- base (LoadError).
What is it that i'm missing here? Also, how is it that ruby know whether it a gem or a file required..does it check to see if the require is a file in the project and then goes on to check for a gem ? How is this process done in ruby?
Any help is much appreciated!

How I include a module (this module has a module inside that) inside another module in Ruby

I have a module as following,
main.rb:
module Main
include Dad::Mam
end
and
in dad.rb:
module Dad
module Mam
puts "Mam is saying you are very lazy..."
end
end
How can I name this file? dad.rb is right?
but when running
$ ruby main.rb
I am getting an Error like,
main.rb:2:in <module:Main>': uninitialized constant Main::Dad
(NameError) from main.rb:1:in'
I need to show the sentance inside the puts under Mam module while running ruby main.rb,
I am confused about using ruby's modules, please anyone help me and guide me..
In this case, since you're just writing a simple script, use #require_relative
require_relative 'dad'
module Main
include Dad::Mam
end
For an actual app or library, you would want to manage the load path (a global variable holding an array that tells ruby where to look for files) and then use a normal require

Ruby: Class object to use in different file

I want to use the object created in main script globally.
for ex I have different module in different file and class in different ruby file
FileNameModA.rb
module A
# ........
# some code here
# ........
end
FileNameModB.rb
module B
# ........
# some code here
# ........
objReport.addReport() # getting an error "ruby uninitialized local variable or object: Main"
end
FileNameClass_Report.rb
class Report
def addreport()
end
end
MainScript.rb
require "FileNameModA"
require "FileNameModB"
require "FileNameClass_Report"
include ModuleA
include ModuleB
objReport = Report.New
objReport.addReport() # Works fine here
Could you please let me know how to create and use object in different file/module of Ruby?
when you require "FileNameModB" it executes the definition of module B and that definition calls objReport.addReport which does not exist in that context
i'm not sure what are you trying to achieve by calling addReport during module definition but you could swap some lines and make it work like this:
require "FileNameClass_Report"
$objReport = Report.New
require "FileNameModA"
require "FileNameModB" # update your file to call $objReport.addReport
include ModuleA
include ModuleB
whole thing looks like a mess though, try to rethink your classes/modules to avoid including them into global object

Load two Ruby Modules/Gems with the same name

I'm trying to use two Gems to access Amazon Web Services (AWS). One is the Amazon 'aws-sdk', the other is 'amazon-ec2'. I'm using the second as the aws-sdk does not cover the cloudwatch section of the amazon services.
The issue is that both load into the same namespace.
require 'aws-sdk' # aws-sdk gem
require 'AWS' # amazon-ec2 gem
config = {:access_key_id => 'abc', :secret_key => 'xyz'}
# start using the API with aws-sdk
ec2 = AWS::EC2.new(config)
# start using the API for anazon-ec2
cw = AWS::Cloudwatch::Base.new(config)
Now this understandably throws an error on the last line as the AWS module is pointing at the first required library, in this case aws-sdk.
NameError: uninitialized constant AWS::Cloudwatch
So, is it possible for me to load one of those into another namespace? Something like
require 'aws-sdk', 'AWS_SDK'
require 'AWS', 'AWS_EC2'
ec2 = AWS_SDK::EC2.new(config)
cw = AWS_EC2::Cloudwatch::Base.new(config)
Or is there another trick I could use here?
Thanks
In Ruby, modules with the same name from different gems don't replace each other. If one gem implements
module AWS
class Foo
end
end
and another implements
module AWS
class Bar
end
end
and you require them both, you will end up with an AWS module that contains both a class Foo and a class Bar (unless the second does something really tricky like explicitly undefining anything already present in the module, before defining its own stuff, which is very unlikely). As long as the second gem doesn't redefine any methods in the first gem (or attempts to use a module as a class or vice versa), they should both work fine. I think you may be looking for the wrong solution.
Edit:
And in fact, what happens for me (in an environment with only these gems present (aws-sdk 1.2.3 and amazon-ec2 0.9.17) and the exact code you listed above) is exactly that:
.rvm/gems/ree-1.8.7-2011.03#ec2/gems/amazon-ec2-0.9.17/lib/AWS/EC2.rb:2: EC2 is not a module (TypeError)
Could it be that an error gets swallowed somewhere and that the module AWS::Cloudwatch hasn't been defined, simply because the initialization of the gem goes awry?
I think I've found a solution that works, let me illustrate it with an example. Suppose we have to files a.rb and b.rb that define the same module with actual name clashes:
#file a.rb
module A
def self.greet
puts 'A'
end
end
#file b.rb
module A
def self.greet
puts 'other A'
end
end
If you need to require both of them, the following seems to do the trick:
require_relative 'a'
TMP_A = A.dup
A.greet # => A
TMP_A.greet # => A
require_relative 'b'
TMP_A2 = A
A.greet # => other A
TMP_A2.greet # => other A
TMP_A.greet # => A
Without the dup, TMP_A will also point to the A defined in b.rb after the require_relative, but the dup will ensure that a real copy is produced instead of simply holding a reference to the module.

Resources