【问题标题】:How to run a Rails application within a gem?如何在 gem 中运行 Rails 应用程序?
【发布时间】:2012-08-20 14:46:12
【问题描述】:

我不确定这种事情是否很常见,但我一直在尝试创建只是 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 中,但我对如何处理 Gemfile 中的 assets 组有点困惑。

# 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

【问题讨论】:

  • 像 Rails 引擎?引擎可以提供路线、模型、资产等,并包含在 gem 中。它基本上是一个 Rails 应用程序,可以安装在另一个 Rails 应用程序中。
  • 就像一个可以独立运行(无需安装)的 Rails 引擎。
  • 或者也许有一种方法可以在没有通常创建的所有目录(app、config、lib、test 等)的情况下运行 Rails 应用程序,因为 widgets 和 foobars 目录会替换这些目录。跨度>
  • gem 用户会与 Web 服务器交互吗?还是只有您的应用程序的代码会这样做?如果是这样,运行 Rails 可能是矫枉过正。请描述“幕后”实际使用这个 Rails 应用程序的情况。
  • @Kelvin 我不知道我是否完全理解你的两个问题的区别。我想像任何其他 Rails 应用程序一样开发 gem 中的代码。当用户使用我的 gem 的可执行文件生成一个新应用程序时,他们应该最终得到一个在我的 gem 中运行 Rails 应用程序的 rackup 文件。

标签: ruby-on-rails ruby


【解决方案1】:

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

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'

有很多选择供您考虑。希望这会有所帮助!

【讨论】:

  • 谢谢!这会有所帮助。我仍然想知道...假设您使用我的 gem 生成一个包含 config.ru 和几个目录的目录。在config.ru 中,我需要做什么来运行gem 的Rails 应用程序,同时将生成的目录添加到config.load_path?我假设类似require 'mygem/rails/app'; run MyGem::Application,但接下来会发生什么?
  • 对不起乔尔,没有意识到我没有接受它。你的回答很有帮助。谢谢!
【解决方案2】:

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

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

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

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

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

【讨论】:

  • Rails 应用程序是一个标准的 Rack 应用程序,所以我真正想做的就是开发一个 Rails 应用程序,并为开发人员提供一种方法来安装我的 gem 中的 Rails Rack 应用程序。跨度>
  • 啊,这清楚了很多。您所描述的正是 Rails 引擎。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 2012-01-22
    • 2016-10-02
    • 1970-01-01
    • 1970-01-01
    • 2011-08-11
    • 1970-01-01
    • 2017-11-22
    • 2011-08-14
    • 1970-01-01
    相关资源
    最近更新 更多