从 Rails 3.1 引擎访问模型

发布于 2024-12-02 08:20:23 字数 3700 浏览 0 评论 0原文

最后一天我一直在努力解决这个问题,这让我发疯!

作为学习练习,我决定将一些代码打包到 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:

An image of the project directory/file listing

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

静待花开 2024-12-09 08:20:23

在引擎助手 (app/helpers/shortener/shortener_helper.rb) 中,将两次出现的 ShortenedUrl 替换为 Shortener::ShortenedUrl

我一开始就发现这个错误很奇怪,因为 ruby​​ 应该在封闭的模块中查找常量。但是助手包含在另一个类中,这可能意味着常量名称解析环境与您在文件中看到的环境不同。

如果您想了解有关命名空间引擎及其行为的更多信息,可以查看 这个很好的答案

In your engine helper (app/helpers/shortener/shortener_helper.rb), replace both occurrences of ShortenedUrl with Shortener::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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文