【问题标题】:Accessing a model from a Rails 3.1 Engine从 Rails 3.1 引擎访问模型
【发布时间】:2011-09-01 10:23:59
【问题描述】:

最后一天我一直在为此苦苦挣扎,这让我发疯了!

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

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                     = [ "gems@jamespmcgrath.com" ]
  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

有什么想法吗?我在网上搜索过,但还没有找到任何真正权威的制作引擎宝石的指南。任何帮助者将不胜感激。

谢谢!

【问题讨论】:

  • 这里应该有一些迁移,没有它们我无法测试你的引擎。
  • 我一直在从 github 测试你的代码,它似乎工作正常(我只添加了一个迁移)。您的 rails 应用程序使用了哪个版本的 rails?我用的是最终的3.1,可能就是这个区别吧。
  • 谢谢伯努瓦。 github 代码有一个创建迁移的生成器。只需键入“rails g 缩短器”。我将修改我的问题以包含此内容。
  • 至于 rails 版本,我认为这可能是问题所在,但我的 gem 文件中有“gem 'rails', '3.1.0'。我将创建另一个 github 项目,我将将我的测试应用推送到。

标签: ruby-on-rails ruby-on-rails-3 rubygems ruby-on-rails-plugins


【解决方案1】:

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

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

如果您想了解有关命名空间引擎及其行为的更多信息,可以查看this excellent answer

【讨论】:

  • Benoit,成功了,你是一个传奇,让我很开心!这很奇怪,因为从应用程序调用帮助程序的代码时工作正常。我想事情在这个过程中的某个地方变得混乱了。我应该对红宝石名称解析有所了解:-)
  • 如果你知道这里到底发生了什么,这将是一个很棒的答案;-)
  • 应该做。希望一些通过命名空间/名称解析/引擎专家会碰巧路过并能够提供启发,而不是我正在寻找一个简单的出路或任何东西:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-02
  • 2020-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多