Distribute a Rails Generator as a Ruby Gem [duplicate] - ruby-on-rails

This question already has answers here:
Rails 3 generators in gem
(2 answers)
Closed 8 years ago.
I am fairly new to Ruby/Rails framework. I have a simple generator in my Rails application at lib/generators. The generator's function is to copy one of the files in the templates/myfile.yml directory into config/myfile.yml.
Now I would like to use this generator in another app. So, I would like to package this as a gem. I have generated gem using bundler and it contains the following file structure:
lib/
mygem/
version.rb
generators/
mygem/
install/
templates/
somefile.yml
install_generator.rb
USAGE
mygem.rb
mygem.gemspec
Gemfile
Gemfile.lock
LICENSE.txt
Rakefile
README.md
Content of install_generator is as follows:
require 'rails/generators'
module Mygem
module Generators
class InstallGenerator < Rails::Generators::Base
source_root File.expand_path('../templates', __FILE__)
def generate_something
copy_file "something.yml", "#{Rails.root}/config/something.yml"
end
end
end
end
Following is the content of mygem.gemspec:
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'mygem/version'
Gem::Specification.new do |spec|
spec.name = "mygem"
spec.version = MyGem::VERSION
spec.authors = ["Swaroop SM"]
spec.email = ["myemail#gmail.com"]
spec.description = %q{Something}
spec.summary = %q{Something}
spec.homepage = ""
spec.license = "MIT"
spec.files = `git ls-files`.split($/)
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ["lib"]
spec.add_development_dependency "bundler", "~> 1.3"
spec.add_development_dependency "rake"
end
I reckon there is something missing in my lib/mygem.rb
require "mygem/version"
module Mygem
# Your code goes here...
end
I have no problem in building and pushing it to rubygems.org.
Inorder to use this in one of my rails app's, I added this to the Gemfile and run bundle install. The problem is now when I run rails g mygem:install it throws an error that says:
Could not find generator mygem:install.
What am I doing wrong?

I solved the issue. I had forgotten to add rails as a dependency in my gemspec file. i.e., I had to include the following in mygem.gemspec:
spec.add_development_dependency "rails", "~> RAILS_VERSION"

Related

Load Assets Using a Gem (Having Troubles Won't Load Assets)

I have a theme I'm constantly using on my sites. I've been trying to load css, js and plugin folder (included with the theme) assets through a gem.
Sprockets::FileNotFound: couldn't find file 'phcthemes' with type 'application/javascript'
If I take out the javascript (css only) this doesn't execute and shows up exactly like this in compiled asset
*= phcthemes
My thoughts app wasn't recognizing the gem, I tried using isolate_namespace (commented out for now) also tried several different config using the info from answer below to no avail.
Main App application.css
*= phcthemes
Main App application.js
// require phcthemes
lib/phcthemers.rb
require "phcthemes/version"
module Phcthemes
class MyRailtie < Rails::Railtie
end
class Engine < ::Rails::Engine
# Isolate Namespace
#isolate_namespace Phcthemes
# Initialize Assets
initializer :assets do |config|
Rails.application.config.assets.precompile += %w{ application.js application.css }
Rails.application.config.assets.paths << root.join("app", "assets", "javascripts")
Rails.application.config.assets.paths << root.join("app", "assets", "stylesheets")
end
end
end
phcthemes.gemspec
$:.push File.expand_path("../lib", __FILE__)
# Maintain your gem's version:
require "phcthemes/version"
Gem::Specification.new do |spec|
spec.name = "phcthemes"
spec.version = Phcthemes::VERSION
spec.authors = ["BradPotts"]
spec.email = ["bradley.j.potts#gmail.com"]
spec.homepage = "http://phcnetworks.net"
spec.summary = "PHCThemes"
spec.description = "PHCNetworks theme with mtdevise and assets built in."
spec.license = "GPL-3.0"
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.files = Dir["{app,config,db,lib}/**/*", "LICENSE", "Rakefile", "README.md"]
# Main Structure & Security
spec.add_dependency "rails", "~> 4.2.5.2"
# Development & Testing
spec.add_development_dependency "sqlite3"
spec.add_development_dependency "bundler", "~> 1.11"
spec.add_development_dependency "rake", "~> 10.0"
spec.add_development_dependency "rspec", "~> 3.0"
end
There's some code missing from your Engine class.
Include the following
initializer :assets do |config|
Rails.application.config.assets.precompile += %w{ myfile.js myfile.css }
Rails.application.config.assets.paths << root.join("app", "assets", "javascripts")
Rails.application.config.assets.paths << root.join("app", "assets", "stylesheets")
end
and then include your files in app/assets/javascripts or app/assets/stylesheets in your gem directory. I'd be surprised if it didn't work the same for the vendor directory or any other directory.
When the gem is installed to a Rails app, you'll still need to put require statements in application.css and application.js. By the way, your CSS requirement statement is incorrect - it should be *= require phcthemes
The Railtie docs say that a Railtie class is needed when running initializers, so include the following class inside your main gem module:
class MyRailtie < Rails::Railtie
end
That should do it. You don't actually have to change the gemspec at all.
You can see my socket_helpers gem for an example. That's what I was building when I encountered this same issue.

Unable to load classes from my gem to my rails app

I have some common code that I want to share between couple of my rails app.
I've generated my gem like so :
bundle gem document-common
My gemspec looks like so :
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'document_common/version'
Gem::Specification.new do |spec|
spec.name = "document_common"
spec.version = DocumentCommon::VERSION
spec.authors = ['Author']
spec.email = ['test#domain.com']
spec.summary = 'Common Models and Lib'
spec.description = 'Common Models and Lib'
spec.homepage = 'google.com'
spec.license = 'WTFPL'
spec.files = Dir["{app,config,db,lib}/**/*", "LICENSE", "Rakefile", "README.rdoc"]
spec.test_files = Dir["spec/**/*"]
spec.test_files.reject! { |file| file.match(/[.log|.sqlite3]$/) }
spec.require_paths = ["lib"]
spec.add_development_dependency "bundler", "~> 1.11"
spec.add_development_dependency "rake", "~> 10.0"
end
In my lib folder I have this :
document_common
document_common.rb
Folder document_common and ruby file document_common.rb, and the ruby file has this content :
require 'document_common/version'
module DocumentCommon
# Your code goes here...
end
Then inside document_common there is a version.rb with this content :
module DocumentCommon
VERSION = '0.1.0'
end
And document.rb with this content:
module DocumentCommon
class Document < ActiveRecord::Base
end
end
So I push this gem to my git repo. And then I add this gem info to my Gemfile in the rails 4 app do a bundle install, but when I refer to DocumentCommon::Document I get this error :
NameError: uninitialized constant DocumentCommon::Document
However if I retrieve the info about the version DocumentCommon::VERSION I get no errors and get the actual version. Also when I do DocumentCommon.constants I get [:VERSION]. What am I doing wrong here? What do I need to do to have access in my main rails app to DocumentCommon::Document model?
You can use the autoload, check out the devise gem does exactly that:
https://github.com/plataformatec/devise/blob/master/lib/devise.rb

cannot load such file -- mygem

I have created a gem called "mygem"(dummy name).
I have built the gem using cmd
gem build mygem
and I have installed the gem as well.
I checked the installation by running
gem list
My gem is listed correctly
But in the irb I am not able to load the gem. Running
require "mygem"
is thorughing the following error
cannot load such file -- myGem
Below is my gemspec
Gem::Specification.new do |spec|
spec.name = "mygem"
spec.version = Mygem::VERSION
spec.authors = ["ABC"]
spec.email = ["ABC#example.com"]
spec.summary = %q{TODO:}
spec.description = %q{TODO:}
spec.homepage = ""
spec.license = "MIT"
spec.files = `git ls-files`.split("\n")
spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.add_development_dependency "bundler", "~> 1.6"
spec.add_development_dependency "rake", "~> 10.0"
spec.add_development_dependency "rspec"
end
It will be great if you can help me out in this. Thanks in advance
It seems that you have created myGem.rb (or like) file, containing myGem class and forget to add it to git.
Why git? Because you use git to build the list of files for your gem:
spec.files = `git ls-files`.split("\n")
To solve the issue you should either specify files to include explicitly, or add all the necessary files to git (so that git ls-files command returns everything needed for gem to be run properly.)
Hope this helps.
May be some file or class name is wrong?
The fact that the error says "myGem" instead of "mygem" makes me think that you have something like my_gem.rb or class MyGem somewhere

Rails 4, custom gem with generator 'Could not find generator'

I'm building a gem simply to go through the processes, and I'm trying to add a generator to it. When I run $ rails g, my generator shows up:
Mygem:
mygem:install
but rails doesn't recognize it
rails g mygem:install
Could not find generator mygem:install.
I have my gem pointed to the latest version in my gemfile
#mygem/lib/rails/generators/mygem_generator.rb
require 'rails/generators'
require 'rails/generators/base'
module Mygem
class InstallGenerator < Rails::Generators::Base
def test
puts 'hi'
end
end
end
.
-mygem
- lib
- generators
- mygem
mygem_generator.rb
- mygem
version.rb
mygem.rb
- pkg
mygem-0.0.1.gem
.gitignore
Gemfile
LICENSE.txt
README.md
Rakefile
mygem.gemspec
.
#mygem.gemspec
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'mygem/version'
Gem::Specification.new do |spec|
spec.name = "mygem"
spec.version = Mygem::VERSION
spec.authors = ["me"]
spec.email = ["email#email.com"]
spec.summary = %q{lalaala}
spec.description = %q{lalalalal}
spec.homepage = ""
spec.license = "MIT"
spec.files = `git ls-files -z`.split("\x0")
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ["lib"]
spec.add_development_dependency "bundler", "~> 1.5"
spec.add_development_dependency "rake"
end
We've just made a gem, and have a generator which allows you to call rails generate exception_handler:install, like this:
#lib/generators/my_gem/install_generator.rb
module MyGem
class InstallGenerator < Rails::Generators::Base
def test
puts "hi"
end
end
end
This should help you - it works for us
I faced this issue after publishing my first public gem, it's because the bundler, or let's say the Rails app don't have access to the actual repository with the generator (I believe so).
I kept including gem 'spree_custom_checkout'
no luck to see the gem's generator when typing rails g.
Then I did this:
gem 'spree_custom_checkout', github: '0bserver07/Spree-Custom-Checkout'
and bam the generator shows up!
steps:
I did `gem build spree_custom_checkout.gemspec.
add it to the github repo, and push to the repostiory.
link to the repository.

Gem with shared models using devise and carrierwave

I have two apps that share several models. I created a gem that contains those models. Minus carrierwave functions and devise methods, it works great (commented them out to test). However when I add them back in I get errors:
undefined method mount_uploader
undefined method devise
I was able to get carrierwave partially working by placing this at the top of one of the models,
require "carrierwave"
require "carrierwave/orm/activerecord"
it would allow the file to upload but it wouldn't save it in the uploads folder, just in the temp one, and it would put the tmp hash in the database instead.
here is my gemspec-
journalbooks_core.gemspec
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'journalbooks_core/version'
Gem::Specification.new do |spec|
spec.name = "journalbooks_core"
spec.version = JournalbooksCore::VERSION
spec.authors = [NAME]
spec.email = [EMAIL]
spec.description = "Contains the shared models of journalbooks.com and creative-queue.com"
spec.summary = ""
spec.homepage = ""
spec.license = "MIT"
spec.files = `git ls-files`.split($/)
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ["lib"]
spec.add_development_dependency "bundler", "~> 1.3"
spec.add_development_dependency "rake"
spec.add_dependency "carrierwave", "= 0.9.0"
spec.add_dependency "devise"
end
Here is the journalbooks_core.rb that runs initially
require "journalbooks_core/version"
module JournalbooksCore
require "models/virtual_request"
require "models/creative_user"
require "models/user"
require "models/virtual"
require "models/cov_order"
end
and here is the model I have been trying to get to work
class CreativeUser < ActiveRecord::Base
require "uploaders/avatar_uploader"
require "carrierwave"
require "carrierwave/orm/activerecord"
...
mount_uploader :avatar, AvatarUploader
...
end

Resources