Ruby 如何从外部访问配对的Padrino应用程序模型(不是在控制器中,而是在独立脚本中)
我有一个名为Gusy的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/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
现在,在您的新应用程序中,转到REPLbundle 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
?
在我看来,我们不应该这样做。在我看来,数据库连接是每个应用程序都需要的东西
应该在本地定义,因为它可能包含访问它或类似内容的特定凭据。