How to apply refinements / monkey-patches globally via environment.rb? - ruby

Lets take the example from the Rainbow gem:
using Rainbow allows to color string objects directly like so 'Hi'.green.
However, when I tried to add using Rainbow to environment.rb in the hopes of being able to access the monkey-patched coloring methods in any file the environment.rb is required in, seems like the coloring methods are not available.
Is there a way to apply the monkey-patch globally once instead of doing using Rainbow in each file separately?

No.
That is literally the whole point of Refinements. If that were possible, Refinements would be fundamentally b0rken.
Refinements are only active in the lexical scope they are used in.

Related

Ruby's `.present?` without Rails?

I'm developing a "Rails-less" Ruby daemon for automation (although in theory it runs within a Rails directory). For general purposes and the principle of the matter, I would like to find the (most) "native"/common way to utilize a Ruby version of .present?/.blank?/.empty?/.nil? to identify if an array or a (hash) value exists and is not empty (i.e., [] or {}).
From what I've read (e.g., Stack Overflow) and tested, all of these functions appear to be Rails-specific methods, part of ActiveSupport(?).
Coming from other web/interpreter languages (PHP, Python, JS, etc.), this is a general logic function most languages (with arrays, which are most) have this functionality built in one way or another (e.g., PHP's isset( ... ) or JavaScript's .length).
I understand there are RegEx workarounds for .blank?, but .present? seems it would require exception handling to identify if it's "present"). I'm having a hard time believing it doesn't exist, but there's little talk about Ruby without Rails' involvement.
Active Support is broken in small pieces so that you can load just what you need. For .blank? and .present? methods it would be enough to require:
require 'active_support/core_ext/object/blank.rb'
As docs say.
Object#nil? , Array#empty? and Hash#empty? already defined so you dont need anything to require to use those.
Make sure active_support gem installed in your system
You can use ActiveSupport without including all rails in your app, that's actually quite common.
nil? and empty? are defined in the standard library.
E.g., String#empty? is simply testing if the length is 0.
To use active support, just install the gem or add it to your gemfile then:
require 'active_support'
The documentation also states you can cherry pick the core extensions you want:
require 'active_support/core_ext/object/blank'

What does it mean to "pollute the global namespace"?

In ruby, some gems choose to "pollute the global namespace".
What does this mean?
How can I see where it's happening?
Why would a gem need to do this?
When faced with two gems that are polluting the global namespace and conflicting, what tradeoffs am I making when I choose to "isolate" one?
For example:
I'm using two gems that are both polluting the global namespace: pry and gli so I'm not able to place my binding.prys where I want anymore.
One solution is to wrap the entire cli in a module:
module Wrapper
include GLI::App
extend self
program_desc "..."
...
exit run ARGV
end
Now I'm able to use my binding.prys wherever I want.
Why did this work?
What tradeoffs am I making when I choose to do "isolate gli"? Or is it "isolate the GLI::App module"?
Ruby has a singular root namespace shared by all code and any constants and globals you define there are universal through the whole application. This makes conflict inevitable if you're not careful about namespacing things.
The module construct is there as a namespace primitive, all constants will be local to that, all classes defined within it. You can also use a class as a namespace if you prefer, it's up to you.
Forcing the include of something into the root namespace is a big problem. That's usually only done in quick scripts that are fairly tiny and self-contained. That's a bad habit to get into when you're doing anything non-trivial as it mashes together all the constants and methods in those two contexts, potentially over-writing them.

ruby module structure insight

I'm new to Ruby and i'm making a Ruby package.
structure is:
eventsims (main folder)
|__lib
|__eventsims {subfolder)
| |__discrete.rb
| |__randgen.rb
| |__simevent.rb
| |version.rb
|__eventsims.rb
If i put all the codes in my three modules file (discrete, randgen and simevent) in the ["Eventsims" module inside the eventsims.rb file], it is easy but there would be up to 1000 lines of code which I don't want
Now I have a "require" lines of code inside eventsim.rb that requires all these four files in the eventsim subfolder.
I can use all the modules, no errors.
for example in the discrete.rb, a module called Discrete with a Calculate class having an expectval method:
Is this how I would be able to use the package after installing it with Rubygems
require "Eventsims"
a = Discrete::Calculate.new([1,0,4,2], [0.2, 0.4, 0.6, 1.0])
a.expectval()
and if yes, is it sensible to have it that way because so many modules I've seen will have something like:
require "eventsims"
Eventsims::someclass.new
which in my case would be
require "eventsims"
Discrete::someclass.new
I'm worried about the consistency of the required file and its namespacing. require eventsim and its different Discrete
Sorry the question is really long.
Unlike some other languages, Ruby does not tie the filesystem names to module hierarchy. If you want to have require "eventsims" provide the module Discrete, you can. Whether or not it's a good idea, it is for you to decide - Ruby is not your Mum. There are two potential pitfalls:
Gem users might get confused, and wonder how to use your gem
Someone in some other gem also defines Discrete and you have a collision.
A compromise between the two approaches (having a distinct namespace and having less to type) is to indeed have a top module EventSims, and for users to include it if they want to access the next level down directly:
# safe usage
require 'eventsims'
EventSims::Discrete::Calculate.new
# easy usage
require 'eventsims'
include EventSims
Discrete::Calculate.new
# restricted easy usage
require 'eventsims'
module MyCode
include EventSims
Discrete::Calculate.new
end
EventSims::Discrete::Calculate.new
This way, you still have namespacing, and you can get rid of it when you know there is no collision in your code. Going the other way around (having no namespacing and trying to isolate the code when a collision does happen) is significantly more difficult.

Advice on how/where to place requires in own gem

I am going through the blog Creating mountable Gem:
Its important to note that you should require your dependent gems explicitly in the root file of your gem. Say if your gem is named my_cool_gem, then you should have my_cool_gem.rb created inside lib folder. If your gem is dependent on strong_parameters, then you need to add these lines:
The author did not mention why it is required to have the dependent gems explicitly in the root file. Can some one explain why this needs to be done?
It's just cleaner. What if you had require statements in various files scattered all over your gem? It'd be a mess to easily see all the dependencies.
This statement:
Its important to note that you should require your dependent gems
explicitly in the root file of your gem.
It is not a strict statement that you have to conform to (to be fair to the author, the word is "should", not "must"). Some people prefer to take a different approach, and e.g. require dependencies only in parts of the library that use them.
However, you do need to consider:
Execution order of require statements that define symbols used elsewhere. You cannot call a DSL method that sets up instance methods for you, if the gem that provides the method has not yet been require-d
You should check that you really do require all correct the dependencies, and your gem functions correctly in projects that do not load them already.
With both of these in mind, it is often quickest and easiest to require dependencies early and and in a way that can be quickly viewed. So the advice is sound; as it was presented in a very short article, covering the statement with caveats and extra background would make the whole thing a lot less pithy.

Adding a "source" attribute to ruby objects using Rubinius

I'm attempting to (for fun and profit) add the ability to inspect objects in ruby and discover their source code. Not the generated bytecode, and not some decompiled version of the internal representation, but the actual source that was parsed to create that object.
I was up quite late learning about Rubinius, and while I don't have my head around it yet fully, I think I've made some progress.
I'm having trouble figuring out how to do this, though. My first approach was to simply add another instance attribute to the AST structures (for, say, a ClosedScope object). Then, somehow pull that attribute out again when the bytecode is interpreted at runtime.
Does this seem like a sound approach?
As Mr Samuel says, you can just use pry and do show-source foo. But perhaps you'd like to know how it works under the hood.
Ruby provides two things that are useful: firstly you can get a list of all methods on an object. Just call foo.methods. Secondly it provides a file_name and line_number attribute for each method.
To find the entire source code for an object, we scan through all the methods and group them by where they are defined. We then scan up the file back until we see class or module or a few other ways rubyists use to define methods. We then scan forward in each file until we have identified the entire class/module definition.
As dgitized points out we often end up with multiple such definitions, if people have monkey patched core objects. By default pry only shows the module definition which contains most methods; but you can request the others with show-source -a.
Have you looked into Pry? It is a Ruby interpreter/debugger that claims to be able to do just what you've asked.
have you tried set_trace_func? It's not rubinius specific, but does what you ask and isn't based on pry or some other gem.
see http://www.ruby-doc.org/core-1.9.3/Kernel.html#method-i-set_trace_func

Resources