从 Rails 3.1 引擎访问模型
最后一天我一直在努力解决这个问题,这让我发疯!
作为学习练习,我决定将一些代码打包到 Rails Gem 中。该代码有一个控制器操作、一条路线、一个模型和一个助手,因此我决定创建 Gem 的最合适方法是将其创建为 Rails 引擎。
一切似乎都进展顺利,除了一件事。当我尝试从控制器或视图(使用引擎的应用程序)中引用模型时,例如:
@su = Shortener::ShortenedUrl.generate("http://stackoverflow.com")
我收到以下错误:
uninitialized constant Shortener::ShortenerHelper::ShortenedUrl
这很奇怪,因为当我从项目控制台执行代码时不会发生错误。我认为这是由于我将所有代码放入“Shortener”命名空间/模块中造成的。我这样做是为了避免在其他应用程序中使用时发生冲突。
代码文件层次结构如下所示:
这是类/模块声明代码(删除内容)相关重要文件
app/controllers/shortener/shortened_urls_controller
module Shortener
class ShortenedUrlsController < ::ApplicationController
# find the real link for the shortened link key and redirect
def translate
# convert the link...
end
end
end
app/models/shortener/shortened_urls
module Shortener
class ShortenedUrl < ActiveRecord::Base
# a number of validations, methods etc
end
end
app/helpers/shortener/shortener_helper
module Shortener::ShortenerHelper
# generate a url from either a url string, or a shortened url object
def shortened_url(url_object, user=nil)
# some code to do generate a shortened url
end
end
lib/shortener/engine.rb
require "rails/engine"
require "shortener"
module Shortener
class ShortenerEngine < Rails::Engine
end
end
lib/shortener.rb
require "active_support/dependencies"
module Shortener
# Our host application root path
# We set this when the engine is initialized
mattr_accessor :app_root
# Yield self on setup for nice config blocks
def self.setup
yield self
end
end
# Require our engine
require "shortener/engine"
Shorter.gemspec
require File.expand_path("../lib/shortener/version", __FILE__)
# Provide a simple gemspec so you can easily use your enginex
# project in your rails apps through git.
Gem::Specification.new do |s|
s.name = "shortener"
s.summary = "Shortener makes it easy to create shortened URLs for your rails application."
s.description = "Shortener makes it easy to create shortened URLs for your rails application."
s.files = `git ls-files`.split("\n")
s.version = Shortener::VERSION
s.platform = Gem::Platform::RUBY
s.authors = [ "James P. McGrath" ]
s.email = [ "[email protected]" ]
s.homepage = "http://jamespmcgrath.com/projects/shortener"
s.rubyforge_project = "shortener"
s.required_rubygems_version = "> 1.3.6"
s.add_dependency "activesupport" , ">= 3.0.7"
s.add_dependency "rails" , ">= 3.0.7"
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
s.require_path = 'lib'
end
我已在 GitHub 上发布了引擎的完整代码:
https://github.com/jpmcgrath/shortener
注意:该引擎有一个生成器来生成所需的迁移文件。类型:
rails g shortener
我还创建了一个显示问题的 Rails 3.1 应用程序(查看项目控制器的第 18 行):
https ://github.com/jpmcgrath/linky
有什么想法吗?我在网上搜索过,但未能找到任何真正权威的制作引擎宝石的指南。任何帮助者将不胜感激。
谢谢!
I have been wrestling with this for the last day and it's driving me NUTS!
As an learning exercise I decided that I would package up some of my code into a Rails Gem. This code has a controller action, a route, a model and a helper so I decided that the most suitable method of creating a Gem would be to create it as a Rails Engine.
Everything seems to be working well, except for one thing. When I try to reference the Model from within a Controller or Views (of an application that uses the engine) e.g.:
@su = Shortener::ShortenedUrl.generate("http://stackoverflow.com")
I get the following error:
uninitialized constant Shortener::ShortenerHelper::ShortenedUrl
It's strange because the error doesn't happen when I execute the code from the projects console. I think that this is caused by the fact I have put all of the code into the "Shortener" namespace/module. I did this so it would help avoid conflicts when used within other applications.
The code file hierachy looks like this:
And here is the class/module declaration code (with the guts removed) of the important files in question
app/controllers/shortener/shortened_urls_controller
module Shortener
class ShortenedUrlsController < ::ApplicationController
# find the real link for the shortened link key and redirect
def translate
# convert the link...
end
end
end
app/models/shortener/shortened_urls
module Shortener
class ShortenedUrl < ActiveRecord::Base
# a number of validations, methods etc
end
end
app/helpers/shortener/shortener_helper
module Shortener::ShortenerHelper
# generate a url from either a url string, or a shortened url object
def shortened_url(url_object, user=nil)
# some code to do generate a shortened url
end
end
lib/shortener/engine.rb
require "rails/engine"
require "shortener"
module Shortener
class ShortenerEngine < Rails::Engine
end
end
lib/shortener.rb
require "active_support/dependencies"
module Shortener
# Our host application root path
# We set this when the engine is initialized
mattr_accessor :app_root
# Yield self on setup for nice config blocks
def self.setup
yield self
end
end
# Require our engine
require "shortener/engine"
shortener.gemspec
require File.expand_path("../lib/shortener/version", __FILE__)
# Provide a simple gemspec so you can easily use your enginex
# project in your rails apps through git.
Gem::Specification.new do |s|
s.name = "shortener"
s.summary = "Shortener makes it easy to create shortened URLs for your rails application."
s.description = "Shortener makes it easy to create shortened URLs for your rails application."
s.files = `git ls-files`.split("\n")
s.version = Shortener::VERSION
s.platform = Gem::Platform::RUBY
s.authors = [ "James P. McGrath" ]
s.email = [ "[email protected]" ]
s.homepage = "http://jamespmcgrath.com/projects/shortener"
s.rubyforge_project = "shortener"
s.required_rubygems_version = "> 1.3.6"
s.add_dependency "activesupport" , ">= 3.0.7"
s.add_dependency "rails" , ">= 3.0.7"
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
s.require_path = 'lib'
end
I have published the entire code of the engine on GitHub:
https://github.com/jpmcgrath/shortener
NOTE: this engine has a generator to generate the required migration file. Type:
rails g shortener
I have also created a rails 3.1 app that exhibits the problem (look at line 18 of the projects controller):
https://github.com/jpmcgrath/linky
Any ideas? I have scoured the web, but have not been able to find any really definitive guide to making Engine Gems. Any helpers would be much appreciated.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在引擎助手 (
app/helpers/shortener/shortener_helper.rb
) 中,将两次出现的ShortenedUrl
替换为Shortener::ShortenedUrl
。我一开始就发现这个错误很奇怪,因为 ruby 应该在封闭的模块中查找常量。但是助手包含在另一个类中,这可能意味着常量名称解析环境与您在文件中看到的环境不同。
如果您想了解有关命名空间引擎及其行为的更多信息,可以查看 这个很好的答案。
In your engine helper (
app/helpers/shortener/shortener_helper.rb
), replace both occurrences ofShortenedUrl
withShortener::ShortenedUrl
.I found this error weird at the beginning, because ruby is supposed to look for constants in the enclosing module. But helpers are included in another class, which could mean that the constant name resolution environment isn't the same as the one you see in the file.
If you want to know more about namespaced engines and their behaviour, you can look at this excellent answer.