Where are .gemspecs located? - ruby-on-rails

Where do you find a .gemspec file related to a gem?
For example; Rapidfire for implementation of another gem into its engine?
Where are these .gemspec files located because I can't for the life of me find it and I've checked every folder associated with Rapidfire
Gem::Specification.new do |s|
s.add_dependency "devise"
end
Where do I add this to make Devise work in Rapidfire?

.gemspec files are located in the root of the repo. For example, here you can find the rapidfire.gemspec
Then the gem is packaged, the spec is serialized into a Ruby structured and stored in the metadata file within the gem.
If you download a gem, and rename the file from .gem to .zip (a .gem is essentially a zip file) you can explore its content. You'll find a metadata.gz file that is a compressed file, that stores the .gemspec data.
--- !ruby/object:Gem::Specification
name: rapidfire
version: !ruby/object:Gem::Version
version: 2.1.0
platform: ruby
authors:
- Yuva Kumar
autorequire:
bindir: bin
cert_chain: []
date: 2015-02-19 00:00:00.000000000 Z
...

Related

Rails Engine not loading from gemfile

Hello I am new to Rails Engine , I have followed ruby official documentation for "Creating Rails Engine" http://guides.rubyonrails.org/engines.html After creating Plugin I have added plugin name in gemfile to load the engine
gem 'product_search', :path => 'product_search/engines/product_search'
but it always through error The path /var/www/sites/web_service/product_search/engines/product_search does not exist.
The Plugin name is "ProductSearch"
I have also changes the pathname
gem 'product_search', :path => 'ProductSearch/engines/product_search'
[It is the Directory structure of the plugin:]
http://i.stack.imgur.com/hRh1X.png
Thanks in advance..!!!
From the documentation:
At the root of this brand new engine's directory lives a
blorgh.gemspec file. When you include the engine into an application
later on, you will do so with this line in the Rails application's
Gemfile:
gem 'blorgh', path: "vendor/engines/blorgh"
Don't forget to run bundle install as usual. By specifying it as a gem
within the Gemfile, Bundler will load it as such, parsing this
blorgh.gemspec file and requiring a file within the lib directory
called lib/blorgh.rb. This file requires the blorgh/engine.rb file
(located at lib/blorgh/engine.rb) and defines a base module called
Blorgh.

Create a rails plugin to preprocess assets

I created a small CSS preprocessor, which is somewhat similar to SASS, and now I would like to test it in a 'real life' scenario, so I'm trying to create a rails plugin for it, like the way sass-rails works.
I tried this, without being really sure of what I was doing:
require 'toss-ruby'
require 'sprockets'
module Toss
module Rails
class Template < ::Tilt::Template
def prepare
end
def evaluate(scope, locals, &block)
g = ::Toss::Generator.new
g.parse_string data
g.generate_string
end
end
end
end
Sprockets.register_engine '.toss', ::Toss::Rails::Template
According to the documentation, the last line should register my template so sprockets can use it, but it doesn't happen, so I assume it's never called. How do some gems like thin, sass-rails, etc... manages to work only by being put in a Gemfile ? When and how is their code called ?
There is a convention that executes code in gems that are included in your Gemfile.
If a file exists in the lib directory of a gem's codebase with the same name as the gem and with a .rb extension, it is required by default when Bundler loads the gem.
Take a gem called "Mygem" as a example. This is a typical directory structure for a gem:
mygem/ (gem's root directory)
|-- lib/
| |-- mygem.rb <-- automatically required!
| `-- mygem/
| |-- base.rb
| `-- version.rb
|-- test/
|-- bin/
|-- Rakefile
`-- mygem.gemspec
When Bundler loads the 'mygem' gem, it automatically requires lib/mygem.rb. Rails plugins and engines rely on this behavior to load their code. Typically, they use this file to require other files in the lib directory. In this case, the lib/mygem.rb file may require lib/mygem/base.rb file, etc.
While developing a gem, it's common to add it to your Gemfile by using the Bundler :path directive, which tells Bundler to look for the gem at a certain path on your local filesystem, rather than on rubygems. Let's assume you are building your gem under the vendor/engines directory of your test application.
Your test app's Gemfile:
gem 'rails'
gem 'mygem', path: './vendor/engines/mygem'
When the Rails app is started, one of the first steps is to load it's gems. When the 'mygem' gem is loaded, Bundler requires './vendor/engines/mygem/lib/mygem.rb' which executes the code in it. Any code you put in there will be run even before Rails is initialized.
If you have code that needs to be run as part of application initialization, you need to follow the guide for creating Rails plugins/engines. Typically, you'll inherit your plugin from ::Rails::Engine and call initializer in it and pass a block containing your initialization code.
With all this in mind, have a look at source code for the sass-rails gem again, specifically lib/sass-rails.rb which gets required when the gem is loaded and how it recursively requires lib/sass/rails/railtie.rb, which does the necessary setup and initialization for the plugin to integrate with Rails.

How to read files (.yml) from a Gem

I want to read a .yml file included in a Rails Engine Gem from my main_app. The file is located at config/test.yml.
IO.read("config/test.yml") fails with No such file or directory # rb_sysopen
If i move the file into the main app, everything works fine. But i need this file in a Gem.
Solution 1
You can store the root path in a constant from your main gem file and retrieve it in other locations of your code. You must ensure that the gem got initialized before the code in your app runs otherwise you'll have an errors because the constant won't be defined.
# lib/my_gem.rb
GEM_ROOT = File.expand_path("../..", __FILE__)
# app/.../some_class.rb
IO.read("#{GEM_ROOT}/config/test.yml")
Solution 2
The most advisable, you can get the gem path programmatically from Bundler, then use that root path to retrieve the full path of your yml file.
Have a look at this answer that you can easily adapt to your case
You should be able to load app yaml files by doing this in your gem:
YAML.load_file('config/test.yml')

How to run a Rails application within a gem?

I'm not sure if this sort of thing is very common, but I keep finding myself trying to create gems that are just wrappers around a Rails application.
My gem will have a generator to create a config.ru but the Rails application will live inside the gem's lib directory. I need to know how to "embed" a Rails application and configure it so that it can be run inside the gem.
For example:
$ mygem new project
mygem created a directory called "project" with the following files:
project/config.ru
project/widgets/
project/foobars/
My gem will also generate some directories that will need to be added to Rails somehow so that I can access the code in those directories from the Rails app living inside the Gem.
Any help or advice you can give me would be appreciated.
To clarify, I'm not trying to create a Rails engine, or plugin to a Rails application. I'm trying to create a fully-fledged Rails application, but package it as a gem so that a user of my gem can run the gem (the rails app) without needing to know that it's using Rails behind the scenes.
Update: Okay, I've got a little bit working now. I've created the gem and generated the rails project inside the gem's lib directory.
$ bundle gem my_gem && cd my_gem/lib
$ rails new my_gem --skip-bundle
Which leaves me with:
my_gem/
my_gem.gemspec
bin/my_gem
lib/
my_gem.rb
my_gem/
version.rb # generated by bundler
# the rails app:
app/
config/
Gemfile
...etc
Since this gem requires Rails, I started adding the gems defined in the Rails Gemfile as dependencies in the gem's Gemspec, but I'm a little confused as to how to handle the assets group in the Gemfile.
# Rails Gemfile
group :assets do
gem 'sass-rails', '~> 3.2.3'
gem 'coffee-rails', '~> 3.2.1'
gem 'therubyracer', :platforms => :ruby
gem 'uglifier', '>= 1.0.3'
end
# gemspec
Gem::Specification.new do |gem|
gem.name = "my_gem"
# ...
gem.add_dependency 'rails', '3.2.8'
gem.add_dependency 'sqlite3'
gem.add_dependency 'jquery-rails'
# how to add the assets group gems?
end
Try this and see if it helps you make progress.
Gems are just directories of files, and you can put whatever files you want into a gem.
Create:
Create a blank gem full-blown Rails project:
$ bundle gem my_gem
Then a Rails app:
$ rails new my_app --skip-bundle
Copy the Rails files into the gem:
$ cp -R my_app/* my_gem
Bundle everything into your Rails app:
$ cd my_gem
$ bundle install --binstubs --path vendor/bundle
$ cd -
Make the Rakefile have the gem tasks and the Rails setup:
#!/usr/bin/env rake
require "bundler/gem_tasks"
require File.expand_path('../config/application', __FILE__)
MyApp::Application.load_tasks
Verify that it starts:
$ rails server
Load Path:
To control where Rails looks for files, such as "external" configuration files, you can use the file config/application.rb with any directory paths like this:
# Add additional load paths for your own custom dirs
# config.load_paths += %W( #{config.root}/../customdir )
Note the ".." which means go above the Rails directory. This gives you a path relative to the gem.
If you prefer you can specify an absolute path, for example if you know the user will always keep his external files in "~/myfiles/". You can also choose to use ENV vars to send in whatever directory you want.
If you read about load path capabilties, look for lines that are shorthand for adding a directory to the front of the load path because you may want to put your external diretories first:
$:.unshift File.dirname(__FILE__)
Gem Build:
Edit my_gem.gemspec to add your own description, homepage, summary, etc. then build:
$ gem build my_gem.gemspec
Successfully built RubyGem
Name: my_gem
Version: 0.0.1
File: my_gem-0.0.1.gem
Now your Rails app is packaged as a gem.
The config.ru should be a typical Rails one. No special changes AFAIK.
When your user wants to install your app:
$ gem install my_gem
The gem will install in the user's typical gem directory. If you want to adjust this, see this page on rubygems: http://docs.rubygems.org/read/chapter/3
Crate:
You may also want to investigate the Crate project:
Crate: Packaging Standalone Ruby Applications
http://www.slideshare.net/copiousfreetime/crate-packaging-standalone-ruby-applications
Rack:
To use config.ru here is the typical Rails setup:
# Rails.root/config.ru
require "config/environment"
use Rails::Rack::LogTailer
use ActionDispatch::Static
run ActionController::Dispatcher.new
For your project, you want to require some files before Rails. You'll want to learn about the Ruby "require" and how it finds files using LOAD_PATH.
The easy way:
# Rails.root/config.ru
require_relative 'filename'
require "config/environment"
Or to put the user's custom directory up couple directory levels:
require './../../filename' # not the best for security
Or to use an absolute path, read about File.expand_path:
File.expand_path(__FILE__)
Or to use the current directory and put it on the load path:
$LOAD_PATH.unshift(File.dirname(__FILE__))
require 'filename'
Lots of choices for you to consider. Hope this helps!
What about the question, "How am I going to run the Rails application inside the gem?".
A Rails application has controllers and views to run a web server. What you need are actions to create, list, update, and destroy. Exposing these actions without a web server is essentially having such methods in a class. That's a normal standard type of gem in the first place.
So maybe your questions is really, how do I write a gem where I have ActiveRecord, and the other Rails stuff.
First, you need to make your gem dependent on the Rails gems you need. You do this in the gemspec file for your gem.
Then it really is just a matter of your gem code doing a require of the right Rails gems you need.
I'm not sure if this will help, as I read through everything and I couldn't find the motivation behind why you were doing this. One of the reasons I came up with was making something that can be used on a desktop environment. In that case you could try using something like Bowline. If you just want to provide an application that others can download and use and install themselves, then you can probably assume they can follow at least basic developer kind of instructions and you could just provide the whole app on github or as a zip file. See an example of someone else doing something similar over on Fat Free CRM's github page.

Unpacked gem in vendor/gems not in a versioned directory

I unpacked a gem into my vendor/gems directory and tried to run my Rails app.
I got this message:
Unpacked gem in vendor/gems not in a versioned directory
I don't understand this error and judging by the Google search results for this error there are not many people who have experienced this problem.
Could this mean I also need to vendor Rails to use vendor/gems?
The much easier and more robust way is to use gem dependencies.
Then if you want to unpack your gems into vendor/gems its as easy as typing:
rake gems:unpack
You do not need to vendor rails in order to vendor gems, the error appears to be a user error you are decompressing the gem into the wrong location and missing some version info.
You don't need to vendor Rails to use vendor gems.
Normally gems unpack to a directory called something like vendor/gems/some_gem-1.2.3. Check that all your vendored gem directories follow this pattern (i.e. GEM_NAME-VERSION).
Did you do this manually or using rake? Since a gem in the vendor/gems directory has this format - gem-name-VERSION.
For example the ruby-openid gem will be unpacked to vendor/plugins/ruby-openid-2.1.7/.
Try using rake gems:unpack to unpack the gems.

Resources