I am creating a graphics library gem.
When creating a gem it seems that it is important to make sure that there are no conflicts with other gems or other code.
For example, extension (monkeypatch) methods are called from within my gem code.
class Array
def sum
inject(0.0) { |result, el| result + el }
end
So, the solution seems to be a module.
How to create a module and ensure that there are no conflicts with other code when the gem is downloaded and used by others?
You just do it. Create a module, and use it:
module MyLibrary
class MyGraphicsClass
# ...
end
end
This in no way helps prevent your monkey patches from stomping on other people's toes. There is no way to prevent your modification to Array from potentially breaking other people's code. The solution is to not do that. Patching fundamental parts of the standard library is a horrible practice, and a great way to make sure nobody wants to touch your gem.
Related
I was looking at this blog entry: 3 Ways to Monkey-Patch Without Making a Mess and I noticed something strange:
# Actually monkey-patch DateTime
DateTime.include CoreExtensions::DateTime::BusinessDays
I've never seen this type of include before and I can't seem to find any documentation on it. How is it supposed to work and am I still supposed to still use a require call to bring in the file? I don't see how it could know the definite path and filename otherwise.
include is a standard module method in Ruby.
You will have to require the relevant file (containing the module definition) unless you have some sort of autoloading mechanism as in Ruby on Rails.
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.
If i want to make a class :
class Foo
#methods here
end
that requires lets say FileUtils
do i do
require 'fileutils'
class Foo
#methods here
end
or
class Foo
require 'fileutils'
#methods here
end
To complement fotanus's answer. Anything defined on a separate file rests in the main namespace, wherever you load or require it from. It does not make difference in terms of scope or namespace. Furthermore, local variables cannot be referenced across files.
So your choice should depend on maintainability. If you write the dependencies on the top of the file, it is easy to know the dependency at a glance. On the other hand, if you require within a certain module, it can make it clear that that dependency is only for the particular module. In the older days, I think the former was preferred, but nowadays, where people use the bundler gem, there is a means to see all the dependencies at a glance, so the motivation for the former may have declined.
It will work either way. require works anywhere, and the FileUtils will be available inside and outside of your class.
By what I have seen on github, it is usually on top - just like most of the other languages, by the way.
How should I store the version number of my code inside a ruby gem?
I've seen two techniques in the wild:
<gem root>/VERSION which only contains your semver.
<gem root>/lib/your_gem/version.rb which contains the following code:
module IfYourCodeIsInAModule
class YourGem
VERSION="0.0.1"
end
end
I like 1. because it's really obvious. I like 2. because it's part of my code, I can write to logs with my version number easily.
I don't like 1. because if I want to access the version number from within my code I have to do a file read (not the worst thing ever), I don't like 2. because if my core class extends from another class then I have to have that decendency in the version.rb too (or else get a superclass mismatch) - eg.
module IfYourCodeIsInAModule
class YourGem < OtherWork
VERSION = "0.0.1"
end
end
When you require this file from your actual code for runtime it's all good. When you include it in your gemspec you suddenly need to require 'other_work' to get your Version number!
I'm happy to go and roll my own solution, but this can't be a new problem, what's the community doing, and what's the general wisdom on this?
I am no expert on gem VERSION ethnology, but perhaps this non-expertise makes me all the more average and better suited to answer the questions on "general wisdom".
So, general wisdom is, use Bundler. And once you create your gem by bundle gem my_gem_name, you will see that the bundler automatically creates lib/my_gem_name/version.rb file and requires it from your lib/my_gem_name.rb. So I would suggest that if you decide not to use bundler and roll your own gem on your own, you still should keep a separate version.rb file containing only
module MyGemName
VERSION = "0.0.1"
end
That is, straight under the main module. You then load the version.rb from lib/my_gem_name.rb. Of course, if your code is organized in a more alien way, then you need to improvize more.
What are the things to be careful about while redefining methods in Ruby? Is redefining core library methods okay?
the problems IMHO are
You'll forget about the change.
You'll copy paste a snippet from the internet, which will trigger an error the altered behavior and you'll scratch your head until you get hairless patches.
Another developer will come after your and fight a bug for 3 months, until he finds it's in one of the monkey patches. He'll go to HR, get your address and and show you why not to do monkey patches.
Now, sometimes you need to monkey patch a class (even in the core library, why not). My suggestion is
Put all of your monkey-patches in ONE source folder.
The second thing you say to a new developer after "Hello my name is ..." is the location of that folder and a detailed explanation of what each monkey patch does.
I don't do much monkeypatching myself, but I've heard that rather than doing
class String
def improved_method
# teh codes
end
end
It's better to put the new method into a module, and then include the module
module ImprovedString
def improved_method
# teh codes
end
end
class String
include ImprovedString
end
it makes it easier to find where a method has been defined, and the old version still exists without having to do alias chaining.
I like the other answers. Though, I have to add that:
Sometimes you may only want to redefine methods only for certain instances. You can do this, and it makes it somehow more controlled than changing the functionality for all objects of a certain class - as long as a proper debugger is used for debugging:
class << object_instance
def method_redefinition
return "method_redefinition"
end
end
object_instance.method_redefinition => "method redefinition"
The metioned set of functionalities can also be encapsulated in a mix-in in order to avoid too much nesting and messy "code definition inside code execution":
module M
def method_redefinition
"method_redefinition"
end
end
object_instance.extend M
object_instance.method_redefinition => "method_redefinition"
You're talking about monkey patching and it's dangerous for the following reasons according to wikipedia
Carelessly written or poorly
documented monkey patches can lead to
problems:
They can lead to upgrade problems when the patch makes assumptions about
the patched object that are no longer
true; if the product you have changed
changes with a new release it may very
well break your patch. For this reason
monkey patches are often made
conditional, and only applied if
appropriate.
If two modules attempt to monkey-patch the same method, one of
them (whichever one runs last) "wins"
and the other patch has no effect,
unless monkeypatches are written with
pattern like alias_method_chain
They create a discrepancy between the original source code on disk and
the observed behaviour that can be
very confusing to anyone unaware of
the patches' existence.
Even if monkey patching isn't used,
some see a problem with the
availability of the feature, since the
ability to use monkey patching in a
programming language is incompatible
with enforcing strong encapsulation,
as required by the object-capability
model, between objects.
There's talk of a safer way of monkey
patching coming in ruby 2 called
refinements
This tiny gem might be useful if you're finding yourself running into monkey-patching issues: (https://github.com/gnovos/ctx). I originally wrote it to create more expressive DSLs by allowing alterations to the base objects without doing too much damage elsewhere, but it can probably be put to any number of uses. It gets around some of the monkey-patching issues by scoping method re-definition into arbitrary contexts that can be swapped out as needed.
If I want to redefine a method in some core class (for example, in String, etc), I use ctx_define instead of "def" and then later wrap the section of code that should use the new definition in a ctx block, like so:
class ::String
ctx_define :dsl, :+ do |other|
"#{self[0].upcase}#{self[1..-1]}#{other.capitalize}"
end
end
puts "this" + "is" + "normal" + "text" + "concatination"
# => thisisnormaltextconcatination
ctx(:dsl) { puts "this" + "is" + "special" + "text" + "concatination" }
# => ThisIsSpecialTextConcatination
I only threw it together in a few minutes, so I can't make any guarantees about how robust it is in any number of complicated situations, but it seems to work fine for simple needs. Give it a look if you're interested and see if it is of any help. :)