I'm creating a ruby gem and I've noticed that there doesn't seem to be (to my knowledge) a naming convention for gems. For example, I've seen both:
gem 'foo-bar'
gem 'foo_bar'
Is there some kind of definitive guide/convention for the naming of ruby gems?
The dashed version is for extensions on other frameworks, like rspec-rails and the underscore is for part of the normal gem name and should be camelcased in your classes.
So if you have a gem named foo_bar, the class/module should be named FooBar. If that gem should have a rails extension which ships as a different gem, it should be called foo_bar-rails and the module should be called FooBar::Rails and it should be required as require "foo_bar/rails"
This convention is also what Bundler tries to require.
Admittedly, this convention is not always followed. jquery_rails should actually be jquery-rails and factory_girl_rails should be called factory_girl-rails. But hey, not everything is perfect.
RubyGems convention docs:
Naming gems
Naming patterns
Make your own gem
Turns out that this is answered pretty clearly and succinctly in the rubygems docs: http://guides.rubygems.org/name-your-gem/
(This may be a recent doc addition because I recall searching for this info in the past and not finding it.)
The one advantage is the convention of collapsing foo_bar into module or class FooBar as far as autoloaders go. foo-bar doesn't have a default equivalent.
Generally the underscore version is preferable from a require perspective, but the dashed version does come across as more readable so it tends to get used often.
In a recommendation of #svenfuchs:
underscore => camelized
hyphen => name::space
https://twitter.com/svenfuchs/status/135773593526206464
But it's true that I still see non-coherence behaviors like:
gem 'my_gem`, :require => 'my-gem'
https://twitter.com/#!/svenfuchs/status/135784542819713024
Related
I have a GoogleTranslate service that translates text in my app. The feature works on localhost but in production it raises
uninitialized constant Google::Cloud in my app/helpers/google_translations_helper.rb:4:in `initialize'...
Here is the Gemfile related part :
# use of google API
gem 'google-api-client', '~> 0.11', :require =>
'google/apis/analyticsreporting_v4'
gem 'omniauth-google-oauth2'
gem "google-cloud-translate"
And here is the helper/service initializer:
module GoogleTranslationsHelper
class GoogleTranslate
def initialize
#translation_service = Google::Cloud::Translate.new
end
def translate(text)
#translation_service.translate text.to_s, from: "fr", to: "en"
end
end
end
I wonder if I'm not missing something about gem version or something like that..
Does someone had the problem already?
I assume you are running Rails. Make sure you include:
require "google/cloud/translate"
somewhere reasonable, either at the top of the file that creates the client object (app/helpers/google_translations_helper.rb in your case), or in a global initialization file such as config/application.rb. (The google-cloud-translate library, like most libraries, needs you to require it before you can use it. See the snippets in the documentation for examples.)
It's not completely clear to me why this is working differently between your development and production environments, but there are usually a lot of differences in the initialization procedure between the two environments so it's not too surprising. Just make sure you're in the habit of requiring any library before using it.
As a side note, I would also recommend updating your Gemfile to call for more recent versions of the Google client libraries. Or at least make sure you've done a recent bundle update. As of this writing, google-api-client 0.11 is more than 2 years old; the newest is 0.30.8. And google-cloud-translate is at 1.3.0. It is always possible there are issues if you're on old versions.
I'm using the excellent twitter-bootstrap-rails gem. There is a helper within that gem (NavbarHelper) which is used to generate Bootstrap navbars with a Ruby helper. I want to monkey patch the gem such that the dropdown lists won't have carets.
So, I looked into the source and found the relevant method here. All I have to do is override it. I created a new file in config/initializers called navbar.rb with the following content:
NavbarHelper.module_eval do
def name_and_caret(name)
"HELLO WORLD"
end
end
Presumably, all of the dropdown titles then should be rendered as "HELLO WORLD" in my app (as referenced by the gem source). However, this is not occurring, and the gem does not appear to be monkeypatched at all.
I tried placing puts NavbarHelper.methods - Object.methods in the initializers file, and there were no results, which makes me think that Rails is not loading the gem correctly before the initializers. I have also checked and verified that the gem is not using autoload for its helpers.
Edit
What may be complicating this is the fact that my Gemfile includes the gem in the following manner:
gem 'twitter-bootstrap-rails', git: 'git://github.com/seyhunak/twitter-bootstrap-rails.git', branch: 'bootstrap3'
I'm not sure if this specific versioning means the monkeypatching doesn't work.
Edit #2
It seems there is only one version of the gem on my system, so I don't think that's the issue. Also, I have tried placing require 'twitter-bootstrap-rails at the top of the initializers file, with no results.
The problem is that you patch the method on this module but the module already got included at this point. Try to define this in your application_helper.rb
def name_and_caret(name)
super("blub #{name}")
end
enumerations_mixin gem depends on deprecated method
here's the guilty line
what would be correct approach to patch it?
Quite a lot of patching I am afraid. This method has been replaced by class_attribute, however it works slightly different. Previously it was enough to use write_inheritable_attribute to create new class param, now you need to declare it first and then assign value.
On line 17 it is using 'write_inheritable_attribute` to set those values. It should now read
class_attribute :"acts_enumerated_#{key}" unless respond_to? "acts_enumerated_#{key}"
self.send(:"acts_enumerated_#{key}=", options[key])
Then, everywhere it is using read_inheritable_attribute(:attribute_name) just use self.attribute_name.
The only problem with this is that 'read_inheritable_attribute` returned nil if attribute is not set and the approach above will throw an error. You will notice that all read methods has default value, like (line 56):
read_inheritable_attribute(:acts_enumerated_on_lookup_failure) || :enforce_strict_literals
You will need to look for all those defaults and enforce them within acts as enumerated method:
def acts_as_enumerated(options = {})
valid_keys = [:conditions, :order, :on_lookup_failure]
default_options = {<all the default values from the code>}
options = default_options.merge options
options.assert_valid_keys(*valid_keys)
valid_keys.each do |key|
write_inheritable_attribute("acts_enumerated_#{key.to_s}".to_sym, options[key]) if options.has_key? key
end
However this is not a perfect design. I would probably define class_attribute enumerated_options within append_features method, put all the options there as a hash instead of creating class_attribute for each option. This is absolutely up to you though.
Also please notice that this gem has been written over 4 years ago, and this method might be not the only deprecated one. I am not entirely sure what this gem is supposed to do, but it might be easier to rather implement what you need rather than to use it.
Clone the gem's repo locally and use it in your rails project as a path to a local gem. So specify in your gemfile:
gem :enumerations_mixin, :path => '/local/path/to/gem'
When you will have the gem patched, fork it on github, replace gems origin in /local/path/to/gem/.git/config, push your changes to your fork, and replace that line in your gemfile to the follownig:
gem :enumerations_mixin, :github => 'your_acoount/enumerations_mixin'
Issue the pull-request to the root repo of the gem, and when the request will be accepted, replace that line in your gemfile to the follownig:
gem :enumerations_mixin, :github => 'protocool/enumerations_mixin'
When the gem will have been released the line can be replaced to:
gem :enumerations_mixin, '~> <new_verison>'
When using a rails application template is possible to make so that some default gems (sqlite3, coffescript and sass) are not included in the Gemfile?
I'm sure you've solved this problem in the last 7 years, but for everyone else, the best method I've seen for doing this is to gsub it out of the file:
# Removes sqlite3, coffee-rails, and sass-rails gems
gsub_file "Gemfile", /^gem\s+["']sqlite3["'].*$/,''
gsub_file "Gemfile", /^gem\s+["']coffee-rails["'].*$/,''
gsub_file "Gemfile", /^gem\s+["']sass-rails["'].*$/,''
Yes, just modify your application template file to not include them.
take a look https://github.com/RailsApps/rails3-application-templates
to get a better idea, specifically mongoid templates
Someone know how can I use this option in Rails 3.1?
Now CoffeScript puts a function with .call(this) on each file, but I want to remove this.
EDIT:
"Can't find variableā error with Rails 3.1 and Coffeescript" and "Pattern for CoffeeScript modules" have what I want. I'll change my global vars to use #global scope.
I'd recommend against doing this. See my answer at Pattern for CoffeeScript modules for some of the reasons why. ("Making your CoffeeScript code incompatible with out-of-the-box Rails 3.1" is yet another reason.) Better to just use
window.a = b
or even
#a = b
instead of a = b when you're trying to export something to global scope.
In previous versions of Rails 3.1, bare compilation was enabled. This was classified as a bug, and fixed in RC1.
So while I strongly encourage you not to do this, here's how to turn bare compilation back on: Add
Tilt::CoffeeScriptTemplate.default_bare = true
to your environment.rb.
I do recommend taking advantage of CoffeeScript's closures and following a CommonJS module patter. But sometimes, just sometimes, it is OK to want to use the --bare option. In my case, when rendering a Jasmine spec helper so I could keep things at the top level and also take advantage of the include Sprockets directive in said Jasmine specs.
To that end, I created the "sprockets-blackcoffee" gem, which you can learn about here. https://github.com/metaskills/sprockets-blackcoffee