7

我不确定这种事情是否很常见,但我一直在尝试创建只是围绕 Rails 应用程序包装的 gem。

我的 gem 将有一个生成器来创建一个config.ru,但 Rails 应用程序将位于 gem 的 lib 目录中。我需要知道如何“嵌入”一个 Rails 应用程序并对其进行配置,以便它可以在 gem 中运行。

例如:

$ mygem new project

mygem created a directory called "project" with the following files:

project/config.ru
project/widgets/
project/foobars/

我的 gem 还将生成一些需要以某种方式添加到 Rails 的目录,以便我可以从 Gem 中的 Rails 应用程序访问这些目录中的代码。

您能给我的任何帮助或建议将不胜感激。

澄清一下,我并不是要创建 Rails 引擎或 Rails 应用程序的插件。我正在尝试创建一个成熟的 Rails 应用程序,但将其打包为 gem,以便我的 gem 的用户可以运行 gem(rails 应用程序),而无需知道它在幕后使用 Rails。

更新:好的,我现在有一点工作。我已经创建了 gem 并在 gem 的 lib 目录中生成了 rails 项目。

$ bundle gem my_gem && cd my_gem/lib
$ rails new my_gem --skip-bundle

这给我留下了:

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

由于这个 gem 需要 Rails,我开始将 Rails Gemfile 中定义的 gem 作为依赖项添加到 gem 的 Gemspec 中,但我对如何处理assetsGemfile 中的组有点困惑。

# 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
4

3 回答 3

13

试试这个,看看它是否能帮助你取得进步。

Gems 只是文件的目录,您可以将任何您想要的文件放入 gem 中。

创造:

创建一个空白 gem 成熟的 Rails 项目:

$ bundle gem my_gem

然后是 Rails 应用程序:

$ rails new my_app --skip-bundle

将 Rails 文件复制到 gem 中:

$ cp -R my_app/* my_gem

将所有内容捆绑到您的 Rails 应用程序中:

$ cd my_gem
$ bundle install --binstubs --path vendor/bundle
$ cd -

使 Rakefile 具有 gem 任务和 Rails 设置:

#!/usr/bin/env rake
require "bundler/gem_tasks"
require File.expand_path('../config/application', __FILE__)
MyApp::Application.load_tasks

验证它是否启动:

$ rails server

加载路径:

要控制 Rails 查找文件的位置,例如“外部”配置文件,可以使用 config/application.rb 文件和任何目录路径,如下所示:

# Add additional load paths for your own custom dirs
# config.load_paths += %W( #{config.root}/../customdir )

请注意“..”,这意味着在 Rails 目录之上。这为您提供了相对于 gem 的路径。

如果您愿意,您可以指定一个绝对路径,例如,如果您知道用户将始终将他的外部文件保存在“~/myfiles/”中。您还可以选择使用 ENV vars 发送您想要的任何目录。

如果您阅读有关加载路径功能的信息,请查找用于将目录添加到加载路径前面的简写行,因为您可能希望将外部目录放在首位:

$:.unshift File.dirname(__FILE__)

宝石建造:

编辑 my_gem.gemspec 以添加您自己的描述、主页、摘要等,然后构建:

$ gem build my_gem.gemspec
Successfully built RubyGem
Name: my_gem
Version: 0.0.1
File: my_gem-0.0.1.gem

现在,您的 Rails 应用程序已打包为 gem。

config.ru 应该是一个典型的 Rails 文件。AFAIK 没有特别的变化。

当您的用户想要安装您的应用程序时:

$ gem install my_gem

gem 将安装在用户的典型 gem 目录中。如果您想对此进行调整,请参阅 ruby​​gems 上的此页面:http: //docs.rubygems.org/read/chapter/3

箱:

您可能还想调查 Crate 项目:

架子:

在这里使用 config.ru 是典型的 Rails 设置:

# Rails.root/config.ru
require "config/environment"

use Rails::Rack::LogTailer
use ActionDispatch::Static
run ActionController::Dispatcher.new

对于您的项目,您希望在 Rails 之前需要一些文件。您将想要了解 Ruby “require”以及它如何使用 LOAD_PATH 查找文件。

简单的方法:

# Rails.root/config.ru
require_relative 'filename'
require "config/environment"

或者将用户的自定义目录放在几个目录级别:

require './../../filename'  # not the best for security

或者要使用绝对路径,请阅读 File.expand_path:

File.expand_path(__FILE__)

或者使用当前目录并将其放在加载路径上:

$LOAD_PATH.unshift(File.dirname(__FILE__))
require 'filename'

很多选择供您考虑。希望这可以帮助!

于 2012-09-11T20:16:06.390 回答
0

那么“我将如何在 gem 中运行 Rails 应用程序?”这个问题呢?

Rails 应用程序具有运行 Web 服务器的控制器和视图。您需要的是创建、列出、更新和销毁的操作。在没有 Web 服务器的情况下公开这些操作本质上是在一个类中拥有这样的方法。这首先是一种普通的标准类型的宝石。

所以也许你的问题真的是,我如何在我有 ActiveRecord 和其他 Rails 东西的地方写一个 gem。

首先,您需要使您的 gem 依赖于您需要的 Rails gem。您可以在 gemspec 文件中为您的 gem 执行此操作。

那么这真的只是你的 gem 代码需要你需要的正确 Rails gem 的问题。

于 2012-09-13T21:03:43.753 回答
0

我不确定这是否会有所帮助,因为我通读了所有内容,但找不到您这样做的动机。我想出的原因之一是制作可以在桌面环境中使用的东西。在这种情况下,您可以尝试使用类似Bowline的东西。如果您只是想提供一个其他人可以下载和使用并自行安装的应用程序,那么您可能会假设他们至少可以遵循基本的开发人员说明,您可以在 github 上或以 zip 文件的形式提供整个应用程序。在Fat Free CRM 的 github 页面上查看其他人做类似事情的示例。

于 2012-09-15T12:52:52.330 回答