从Rails 3.1引擎访问模型

Jam*_*ath 5 rubygems ruby-on-rails ruby-on-rails-plugins ruby-on-rails-3

我在最后一天一直在和它搏斗,它正在驱使我努力!

作为一个学习练习,我决定将一些代码打包成Rails Gem.这段代码有一个控制器动作,一个路由,一个模型和一个帮助器,所以我认为最合适的创建Gem的方法是将它创建为Rails引擎.

除了一件事,一切似乎都运作良好.当我尝试从Controller或Views(使用引擎的应用程序)中引用模型时,例如:

@su = Shortener::ShortenedUrl.generate("http://stackoverflow.com")
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

uninitialized constant Shortener::ShortenerHelper::ShortenedUrl
Run Code Online (Sandbox Code Playgroud)

这很奇怪,因为当我从项目控制台执行代码时,不会发生错误.我认为这是因为我已将所有代码放入"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
Run Code Online (Sandbox Code Playgroud)

应用程序/模型/缩略服务/ shortened_urls

module Shortener
  class ShortenedUrl < ActiveRecord::Base

    # a number of validations, methods etc  

  end 
end
Run Code Online (Sandbox Code Playgroud)

应用程序/佣工/缩略服务/ 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
Run Code Online (Sandbox Code Playgroud)

LIB /缩短器/ engine.rb

require "rails/engine"
require "shortener"

module Shortener

  class ShortenerEngine < Rails::Engine

  end

end
Run Code Online (Sandbox Code Playgroud)

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"
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

我在GitHub上发布了引擎的完整代码:

https://github.com/jpmcgrath/shortener

注意:此引擎有一个生成器,用于生成所需的迁移文件.类型:

rails g shortener
Run Code Online (Sandbox Code Playgroud)

我还创建了一个展示问题的rails 3.1 app(查看项目控制器的第18行):

https://github.com/jpmcgrath/linky

有任何想法吗?我已经在网上搜索过,但是还没有找到任何真正明确的制作引擎宝石的指南.任何助手都会非常感激.

谢谢!

Ben*_*ret 3

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

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

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