I saw the following source code in someone's repository:
module Twitter
module Bootstrap
module Rails
require 'twitter/bootstrap/rails/engine' if defined?(Rails)
end
end
end
require 'less-rails'
require 'twitter/bootstrap/rails/bootstrap' if defined?(Rails)
Source
I want to know what's difference when we put require in a module?
There is no difference as far as the require is concerned, i.e., require always loads the file into the global namespace.
It should be noted that, in this case, the inner require will always run, since Rails at that point refers to the module it is within, so the if statement there will always evaluate to true.
This means the code is equivalent to the possibly less confusing:
module Twitter
module Bootstrap
module Rails
end
end
end
require 'twitter/bootstrap/rails/engine'
require 'less-rails'
require 'twitter/bootstrap/rails/bootstrap' if defined?(Rails)
Related
So I have a function reload_config inside a Sinatra helper module which is defined below in helpers.rb.
module Web
module Helpers
def reload_config
require_all 'config/*.rb'
end
end
end
It is then loaded in Web::Base the recommended way using helpers Web::Helpers.
Inside config there is a file called redis.rb which is then loaded by reload_config. At least it should be. Calling on require_all inside my config.ru (top level) effectively loads the content of redis.rb, but inside my helper module it does not.
redis.rb contains assignments to configatron.redis (which should be accessible from any scope level right?)
Another troubling fact: if I change the path I give to require_all it raises an exception.
Also, if I write, for example, puts "Haaaaa!" inside the redis.rb, it is executed when loaded from config.ru but not when loaded from helpers.rb.
What could be the cause of this ? If it has to do with lexical scoping, then why is it impossible to actually execute statements such as puts or configatron.foo = 'hello' ?
Note that require_all and configatron are loaded in config.ru.
The solution is simply to user load_all instead of require_all.
The code would not load not because of some lexical scoping issue but because of that require_all does not load twice the same file. Therefore using load_all solves the problem.
I was looking at the contents of the Ransack ruby gem. Basically, it calls a method called require_constants. And that method itself requires a file:
# ransack.rb
require 'ransack/adapters'
Ransack::Adapters.object_mapper.require_constants
# adapters.rb
module Ransack
module Adapters
def self.object_mapper
#object_mapper ||= instantiate_object_mapper
end
def self.instantiate_object_mapper
if defined?(::ActiveRecord::Base)
ActiveRecordAdapter.new
elsif defined?(::Mongoid)
MongoidAdapter.new
end
end
class ActiveRecordAdapter
def require_constants
require 'ransack/adapters/active_record/ransack/constants'
end
...
# constants.rb
module Ransack
module Constants
The first require copies the content of adapters.rb in ransack.rb, I believe. Hence, we can then reference Ransack::Adapters without an undefined error.
However, when we call require_constants, it appears to copy the contents of Ransack::Constants into the method definition of require_constants.
I find that kind of confusing. We are copying a module inside of a method. What benefit do we get of copying a module inside of a method, rather than just doing it like the other require? Second, I know the module is not a local variable, but I couldn't even define a module in the console when I tried it:
class A
def a
module B end
end
end
SyntaxError: (irb):14: module definition in method body
So what is require doing that does not cause the syntax error?
"Copy" is the wrong word here. require does not copy anything. It reads the source code in the given file and executes that code in Ruby's global ("main") context (unless the file has already been required; then it does nothing and returns false). To quote the docs (emphasis mine):
Any constants or globals within the loaded source file will be available in the calling program’s global namespace.
require does not behave differently inside a method call, or inside a module, or anywhere else, than it does at the top of a file.
When you see require inside a method call the reason is usually that the module is only needed in a particular scenario, and loading it before that scenario occurs would be wasteful (because, for example, the module takes a long time to load or accesses, during loading, resources that are only available in that scenario—think different database drivers or OSes). It does not mean that the module is being loaded "into" the method or the surrounding code, because that's not what require does.
To demonstrate, suppose we have a module like this:
# baby_module.rb
module BabyModule
NAME = "Baby"
end
And suppose we run the following program:
module TheCorner
def self.load_baby_module
require File.expand_path("baby_module", __dir__)
end
end
TheCorner.load_baby_module
if defined?(TheCorner::BabyModule)
puts "#{TheCorner::BabyModule::NAME} is in TheCorner"
elsif defined?(BabyModule)
puts "Nobody puts #{BabyModule::NAME} in TheCorner"
end
As you have perhaps already guessed, this program's output will be:
Nobody puts Baby in TheCorner
So what is require doing that does not cause the syntax error?
Simple: it runs the file.
I am trying to create performance automation framework for my company . Beinbg newbie to ruby field , I thought to keep it simple . Here is structure for performance framewrok
I do have multiple ruby files , as request.rb,payload.rb etc in 'common' folder(as these are containing some utilities) and then my test in test.rb (under one of 'TestFlows->SimpleFlow->test.rb) .
See above structure for more detail
Exact Code , which I am having right now under those files are
request.rb
require 'ruby-jmeter' #(Consider any 3rd party gem )
require 'rubygems'
module Company #Note that i am using same module name 'company'
module Request
def self.send_request()
visit '192.148.1.2' # this is function defined under ruby-jmeter
end
end
end
payload.rb
require 'ruby-jmeter' #(Consider any 3rd party gem )
require 'rubygems'
module Company #Note that i am using same module 'company'
module Payload
def self.get_payload()
------- Again some 'ruby-jmeter' function calls
end
end
end
etc files as well
Test.rb
require 'ruby-jmeter' #(Consider any 3rd party gem )
require 'rubygems'
require 'require_all' #(gem to load all files from folder)
require_all '../../common/'
module Company #Note that i am using same module 'company'
test name:'GooglePerformanceTest' do
defaults domain: 'http://google.com' ,protocol: http
threads name: 'NoOfUsers',scheduler: false,continue_forever:
false, count: 2 do
Request.send_request()
end
end #end of testPlan
view_results_tree
puts "JMX FILE IS GONNA SAVED #
"+Dir.pwd+"/CreatedJMeter_DB2Navigation.jmx"
end.jmx(file: Dir.pwd+"/CreatedJMeter_DB2Navigation.jmx")
end
When I run this programme , it goes to above , I am getting errors of those (3rd party ruby gem's function undefined).
Can anyone point me out my problem regarding above structure & suggest me proper way to do this ?
edit :
I am getting below error
Test.rb:3:in `send_request': undefined method `visit ' for
company::Request:Module (NoMethodError)
Edit
Have defined my changes here & it is working fine
Facing issues while calling method of module(having object of class , contained in another ruby file)
I'm assuming you're using the gem hosted at this repository: https://github.com/flood-io/ruby-jmeter, latest release version (2.13.8).
Looking through the source code and examples, there are a couple things to think about.
The 'visit' method is an alias for a method called 'get' defined here
.
That is an object method, for an object of class RubyJmeter::ExtendedDSL. You are using module methods, and should probably consider making an object and calling the method on that.
obj = RubyJmeter::ExtendedDSL.new
obj.visit '192.148.1.2' # 'visit' is a method alias for 'get'
However, the examples listed by the gem developer follow a different pattern, calling 'visit' from within a closure (the do..end code block, known simply as a 'block' in Ruby). You could rewrite your code to build test plans and run them in this fashion.
It's not clear from what you post why you are using modules. Typically, you use 'include' within a Module or Class to mix in the gem's methods into your namespace. But since you're attempting to use module methods, I'm not sure mixing in object methods will be fruitful.
Since I can't see how your Test.rb file is run, I can't say for sure that your test code is loading your own modules. Typically a 'load' or 'include' statement would be used to load the code you wrote in request.rb and payload.rb
Personally, I'd try to follow the pattern shown by the developer of RubyJmeter; as a second approach, I'd write a class that inherits from RubyJemeter's subclass and extend its behavior to suit. My test code would initialize an object and call its methods directly. (Your Mileage May Vary.)
Updated to add: if you want your module method to stand in place of the object method mentioned, you can simply call the latter inside your method:
def self.send_request()
RubyJmeter::ExtendedDSL.new.visit '192.148.1.2'
end
Doing this essentially creates a disposable object, which is destroyed after the :visit method returns its data.
P.S. Always capitalize your class and module names. It's a Ruby best practice and your module name 'company' will raise warnings from the interpreter.
Usually, I put most of my require statements at the top of a file. While reading the source code for Poltergeist, I noticed the following
module Capybara
module Poltergeist
require 'capybara/poltergeist/utility'
require 'capybara/poltergeist/driver'
require 'capybara/poltergeist/browser'
# more requires
end
end
Actual source
What are the advantages of using require this way?
The advantage in this case is that the Capybara::Poltergeist module exists before those modules are required. Since those modules all extend the Capybara::Poltergeist module, this is just a way to ensure that they aren't loaded before the module is actually available. Placing the require statements after the module definition would have the same effect.
Consider the following:
# foobar.rb
require './bar_module'
module Foo
module Bar
end
end
# bar_module.rb
module Foo::Bar
def baz
"hi!"
end
end
This setup will fail because the non-nested Foo::Bar syntax will expect Foo to already exist by the time this module is called. By changing the first file to:
module Foo
module Bar
require './bar_module'
end
end
The require will work, since Foo::Bar will exist by the time that bar_module starts doing its thing.
In this particular instance, it doesn't have much practical effect, since Poltergeist uses the nested module syntax (module Foo; module Bar) rather than the collapsed syntax (module Foo::Bar), but it's a good practice that basically delineates "these requires expect this module to exist".
I don't know what's the advantage in your example.
I sometimes use require inside a method definition.
I do this for methods which are used rarely, but need large libraries. The advantage: The large library is only loaded, when it is really needed.
require checks, if the library is already loaded. So I have no problem with double loading a library.
I'm currently developing a framework that basically executes another application, e.g. rails within the context of another ruby program. My initial attempt was simply to boot the app like this:
def load_app!
# Load the rails application
require './config/application'
# Initialize the rails application
#app = App::Application.initialize!
end
Problem here, is that the framework's requires conflict with the loaded application so the initialize! call never works although it would in a normal ruby program.
So my question is, if anyone knows a method to basically scope this calls into a unit that behaves like a blank RVM environment. So basically a behavior like this:
require 'json'
puts JSON.generate({:name => "test"})
blank_environment do
puts JSON.generate({:name => "test"})
#=> uninitialized constant JSON
require 'json'
puts JSON.generate({:name => "test"})
end
It's not done with undefining or unloading the currently loaded constants because I don't know all of them because I'm using gems that have other dependencies again.
So is there a cool way? Or any other way to handle this?
UPDATE:
Just came across an idea. Why is ruby's require method always requiring for the global scope? Wouldn't it be a very nice feature to actually scope the loaded modules under the the current module?
module ScopeA
require 'json' #> adds support for ScopeA::JSON
# due to normal ruby scoping everything can be called like normal in here
JSON.parse("something")
end
# JSON should not be available here
module ScopeB
require 'yaml'
YAML.parse("something") # but no JSON, of course
end
Doesn't something like this exist? include already has to know the constants...
Thanks in advance!
Well, after some more research it really doesn't seem possible the way I need it.
I now implemented a basic version using distributed ruby, which doesn't quite satisfy me:
require 'drb/drb'
URI = "druby://localhost:8787"
# Blank environment
pid = fork do
Signal.trap("INT") { puts "Stopping Server.."; exit }
class Application
def call(env)
[200,{},""]
end
end
DRb.start_service(URI, Application.new)
DRb.thread.join
end
# Working environment
DRb.start_service
app = DRbObject.new_with_uri(URI)
puts app.call({})
Process.kill("INT", pid)
Process.wait
If anyone comes up with a better approach, it's highly appreciated!