Ruby 如何从外部访问配对的Padrino应用程序模型(不是在控制器中,而是在独立脚本中)

Ruby 如何从外部访问配对的Padrino应用程序模型(不是在控制器中,而是在独立脚本中),ruby,gem,padrino,Ruby,Gem,Padrino,我有一个名为Gusy的Padrino应用程序,它指定了(续集)模型,如 # gusy/models/seminar.rb class Seminar < Sequel::Model # hopefully irrelevant stuff defined here end 我希望在不创建第二个挂载Gusy的Padrino应用程序的情况下实现这一点(为此,指针包含在生成的Gusy/README.md中) 正如最初声明的那样,如果我想在同一个应用程序中做我想做的事情,我会遇到同样的问题:

我有一个名为Gusy的Padrino应用程序,它指定了(续集)模型,如

# gusy/models/seminar.rb
class Seminar < Sequel::Model
  # hopefully irrelevant stuff defined here
end
我希望在不创建第二个挂载Gusy的Padrino应用程序的情况下实现这一点(为此,指针包含在生成的Gusy/README.md中)


正如最初声明的那样,如果我想在同一个应用程序中做我想做的事情,我会遇到同样的问题:在
gusy/bin
中编写一个与数据库对话的小脚本,就像在调用
padrino控制台时一样。不过,你提出这个问题很好,因为我已经试着围绕这个主题思考了一段时间,这让我陷入其中:)。我已经为你准备了一份报告,解释如何利用我们在帕德里诺的现有资源

自述文件(我随后将粘贴)解释了其背后的原因,并提出了一些问题供我们思考我们实现它们的方式。我很想听听你的想法:)

Padrino中的双子应用程序 本回购协议旨在回答以下问题: 和

问题 简言之,有两个性质类似的问题,都与gemified应用程序中定义的模型有关:

  • 它们需要从其他gems/项目中访问
  • 他们需要从Gemized应用程序的
    bin
    中访问,并执行除启动以外的其他操作 Padrino服务器
榜样 首先是
gemified应用程序
。这是一个配对的Padrino应用程序。它还包含一个模型 名为
SomeModel
,其中有一个名为
property
的字段

然后是
不使用padrino访问双子应用程序
;将gemified应用程序加载到的ruby脚本 访问模型

最后,还有一个
应用程序
,它是一个普通的Padrino应用程序,只需加载
双子应用程序
即可使用 它的模型(
SomeModel

当前Padrino设置的问题 使用
padrino g project Gemized应用程序--orm sequel--gem--tiny创建一个应用程序将为您提供
以下
gempec

# -*- encoding: utf-8 -*-
require File.expand_path('../lib/gemified-app/version', __FILE__)

Gem::Specification.new do |gem|
  gem.authors       = ["Darío Javier Cravero"]
  gem.email         = ["dario@uxtemple.com"]
  gem.description   = %q{Padrino gemified app example}
  gem.summary       = %q{Padrino gemified app example}
  gem.homepage      = ""

  gem.files         = `git ls-files`.split($\)
  gem.executables   = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
  gem.test_files    = gem.files.grep(%r{^(test|spec|features)/})
  gem.name          = "gemified-app"
  gem.require_paths = ["lib", "app"]
  gem.version       = GemifiedApp::VERSION

  gem.add_dependency 'padrino-core'
end
关键点是
gem.require\u路径=[“lib”,“app”]
gem.add\u依赖项'padrino core'

gem.require_paths=[“lib”,“app”]
解释了当我们 把宝石装到别的地方。它不会简单地添加到
$LOAD_PATH
:(

gem.add_dependency'padrino core'
提示我们以后可能会缺少一些东西。会发生什么 对于像ORM或渲染器这样的依赖项?我们应该加载它们吗?我认为这是个问题 你想要达到的目标,但大多数时候我会说是的

我们的gemified应用程序依赖项仍列在我们的
Gemfile
中,该文件将仅添加到 当前范围,不在任何需要我们的
gem应用程序的gem中

第一次尝试解决这个问题 要使这项工作发挥作用,我们应该做两件事:

'models'
添加到
gem.require\u path=[“lib”,“app”]
,使其成为:
gem.require\u路径=[“lib”、“app”、“models”]
。 这将确保
gemified app/models
目录中的任何内容都包含在您的 宝石

为了便于测试,我们将使用
bundler
,并在
无需padrino访问gemified应用程序中使用

测试脚本我们将添加一个如下所示的
Gemfile

require 'gusy'
Gusy::Seminar.create(:name => 'from gusy_fill' # => NameError: uninitialized constant Gusy::Seminar
source 'https://rubygems.org'

gem 'gemified-app', path: '../gemified-app'
gem 'pry'
# gemified-app/gemified-app.gemspec

  # ...

  gem.add_dependency 'padrino-core'
  gem.add_dependency 'padrino-helpers'
  gem.add_dependency 'slim'
  gem.add_dependency 'sqlite3'
  gem.add_dependency 'sequel'
  gem.add_development_dependency 'rake'

  # ...


# gemified-app/Gemfile
source 'https://rubygems.org'

# Distribute your app as a gem
gemspec
require 'gemified-app'

Sequel::Model.plugin(:schema)
Sequel::Model.raise_on_save_failure = false # Do not throw exceptions on failure
Sequel::Model.db = Sequel.connect("sqlite:///" + File.expand_path('../../gemified-app/db/gemified_app_development.db', __FILE__), :loggers => [logger])

require 'some_model'

SomeModel.all.each do |model|
  puts %Q[#{model.id}: #{model.property}]
end
现在,在您的新应用程序中,转到REPL
bundle exec pry
并尝试
要求使用“gemified app”
。 然后尝试
SomeModel.all
。它会失败。为什么?因为你不需要“SomeModel”

但是如果你这样做,它仍然不起作用。为什么?因为没有模型的依赖关系, i、 e.
sequel
sqlite3
(不是直接依赖项,而是通过连接)被加载

这里有两种选择:手动将它们加载到
Gemfile
中,或者将它们定义为 依赖于
gemified app.gemspec
。 我认为后者是一个更好的选择,因为您已经包括了模型,并且 希望它的依赖项随附。它希望:

require 'gusy'
Gusy::Seminar.create(:name => 'from gusy_fill' # => NameError: uninitialized constant Gusy::Seminar
source 'https://rubygems.org'

gem 'gemified-app', path: '../gemified-app'
gem 'pry'
# gemified-app/gemified-app.gemspec

  # ...

  gem.add_dependency 'padrino-core'
  gem.add_dependency 'padrino-helpers'
  gem.add_dependency 'slim'
  gem.add_dependency 'sqlite3'
  gem.add_dependency 'sequel'
  gem.add_development_dependency 'rake'

  # ...


# gemified-app/Gemfile
source 'https://rubygems.org'

# Distribute your app as a gem
gemspec
require 'gemified-app'

Sequel::Model.plugin(:schema)
Sequel::Model.raise_on_save_failure = false # Do not throw exceptions on failure
Sequel::Model.db = Sequel.connect("sqlite:///" + File.expand_path('../../gemified-app/db/gemified_app_development.db', __FILE__), :loggers => [logger])

require 'some_model'

SomeModel.all.each do |model|
  puts %Q[#{model.id}: #{model.property}]
end
你必须明确地包含所有你需要的宝石。这可能看起来很麻烦,但实际上很复杂 公平地说,它让你更好地了解你的应用程序需要什么。最终你会的 意识到你甚至不需要bundler和Gemfile:)

好的,那么,继续启动您的REPL并键入
require'gemified app'
require'some_model'
。 然后尝试
SomeModel.all
。而且。。。它将失败:(.为什么?因为未定义
Sequel::Base
。现在您可能想知道: 我在我的
Gemmified app.gemspec
中提到的
续集发生了什么事?好吧,只是:
一个参考,它不会要求你的宝石。
帕德里诺也不会这样,因为我们正在使用

require 'rubygems' unless defined?(Gem)
require 'bundler/setup'
Bundler.require(:default, RACK_ENV)
在我们的
config/boot.rb
中,只在我们的
Gemfile
上加载所需的gem

所以问题是…我们应该手动加载吗?如果是,在哪里

好吧,因为这本身就是一块宝石,我相信最好的地方是
lib/gemified app.rb
。 加载所需的所有gem将使此文件看起来像:

require 'padrino-core'
require 'padrino-helpers'
require 'slim'
require 'sqlite3'
require 'sequel'

module GemifiedApp
  extend Padrino::Module
  gem! "gemified-app"
end
好了,我们都准备好了…回到REPL,你需要什么

require 'gemified-app'
require 'some_model'
然后尝试
SomeModel.all
。然后…它将失败:(.再次!:/为什么?因为没有连接到 Padrino正在通过
config/database.rb
为我们加载这个

另一个问题出现了……我们是否也应该在gem中包含
config/database.rb
? 在我看来,我们不应该这样做。在我看来,数据库连接是每个应用程序都需要的东西 应该在本地定义,因为它可能包含访问它或类似内容的特定凭据。