简体   繁体   English

如何在gem中运行Rails应用程序?

[英]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. 我不确定这种事情是否很常见,但我一直在发现自己试图创建只是围绕Rails应用程序包装的宝石。

My gem will have a generator to create a config.ru but the Rails application will live inside the gem's lib directory. 我的宝石将有一个生成器来创建一个config.ru但Rails应用程序将存在于gem的lib目录中。 I need to know how to "embed" a Rails application and configure it so that it can be run inside the gem. 我需要知道如何“嵌入”Rails应用程序并对其进行配置,以便它可以在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. 我的gem还会生成一些需要以某种方式添加到Rails的目录,以便我可以从Gem内部的Rails应用程序访问这些目录中的代码。

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. 为了澄清,我不是要创建一个Rails引擎,或者插件到Rails应用程序。 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. 我正在尝试创建一个完全成熟的Rails应用程序,但将其打包为gem,以便我的gem的用户可以运行gem(rails app)而无需知道它在后台使用Rails。

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. 我已经创建了gem并在gem的lib目录中生成了rails项目。

$ 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. 由于这个gem需要Rails,我开始在gem的Gemspec中添加Rails Gemfile中定义的gems作为依赖项,但是我对如何处理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

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. Gems只是文件的目录,您可以将所需的任何文件放入gem中。

Create: 创建:

Create a blank gem full-blown Rails project: 创建一个空白宝石成熟的Rails项目:

$ bundle gem my_gem

Then a Rails app: 然后一个Rails应用程序:

$ rails new my_app --skip-bundle

Copy the Rails files into the gem: 将Rails文件复制到gem中:

$ cp -R my_app/* my_gem

Bundle everything into your Rails app: 将所有内容捆绑到您的Rails应用程序中:

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

Make the Rakefile have the gem tasks and the Rails setup: 使Rakefile具有gem任务和Rails设置:

#!/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: 要控制Rails查找文件的位置,例如“外部”配置文件,您可以将文件config / application.rb与任何目录路径一起使用,如下所示:

# 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. 注意“..”,这意味着要高于 Rails目录。 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/". 如果您愿意,可以指定绝对路径,例如,如果您知道用户将始终将其外部文件保留在“〜/ myfiles /”中。 You can also choose to use ENV vars to send in whatever directory you want. 您还可以选择使用ENV vars发送您想要的任何目录。

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: 编辑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

Now your Rails app is packaged as a gem. 现在您的Rails应用程序打包为gem。

The config.ru should be a typical Rails one. config.ru应该是典型的Rails之一。 No special changes AFAIK. AFAIK没有特别的变化。

When your user wants to install your app: 当您的用户想要安装您的应用时:

$ gem install my_gem

The gem will install in the user's typical gem directory. gem将安装在用户的典型gem目录中。 If you want to adjust this, see this page on rubygems: http://docs.rubygems.org/read/chapter/3 如果你想调整这个,请参阅rubygems上的这个页面: http//docs.rubygems.org/read/chapter/3

Crate: 箱:

You may also want to investigate the Crate project: 您可能还想调查Crate项目:

Rack: 架:

To use config.ru here is the typical Rails setup: 在这里使用config.ru是典型的Rails设置:

# 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. 对于您的项目,您希望在Rails之前需要一些文件。 You'll want to learn about the Ruby "require" and how it finds files using LOAD_PATH. 您将需要了解Ruby“require”以及它如何使用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.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?". 问题是什么,“我如何在gem中运行Rails应用程序?”。

A Rails application has controllers and views to run a web server. Rails应用程序具有运行Web服务器的控制器和视图。 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. 在没有Web服务器的情况下公开这些操作实际上是在类中具有这样的方法。 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. 所以也许你的问题是真的,我怎么写一个我有ActiveRecord的宝石,以及其他Rails的东西。

First, you need to make your gem dependent on the Rails gems you need. 首先,您需要使您的宝石依赖于您需要的Rails宝石。 You do this in the gemspec file for your gem. 您可以在gem的gemspec文件中执行此操作。

Then it really is just a matter of your gem code doing a require of the right Rails gems you need. 那么它真的只是你的宝石代码需要你需要的正确的Rails宝石。

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 . 在这种情况下,你可以尝试使用像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. 如果您只想提供其他人可以下载并使用和安装的应用程序,那么您可以假设他们至少可以遵循基本的开发人员指令,您可以在github或zip文件中提供整个应用程序。 See an example of someone else doing something similar over on Fat Free CRM's github page . Fat Free CRM的github页面上查看其他人做类似事情的示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM