Friendly_id和Active Admin冲突 - 可能是因为revert_freindly_id

时间:2014-08-19 16:13:20

标签: ruby-on-rails activeadmin friendly-id

第一次询问有关堆栈溢出的问题:)

我在friendly_id和主动管理员之间存在冲突(这是一个假设),正如许多线程所讨论的那样。我看过所有这些线程,但我不完全确定它们能解决我的问题。对不起,很长的帖子!

我正在尝试在我的网站上创建友好的产品链接。我添加了friendly_id gem,在我的开发和登台环境中一切正常,但友情链接在生产中失败。这是我的所有代码:

型号:

class Product < ActiveRecord::Base
  extend FriendlyId
  friendly_id :name, use: :slugged
  ...
end

控制器:

class ProductsController < ApplicationController
  before_filter :get_product, only: [:show]
  ...

  private

  def get_product
    @product = Product.friendly.find(params[:id])
  end
end

此时我的所有产品记录都有一个完整的slug字段。我不想在我的管理界面中使用slug,所以当我遇到一个解决方案here时,我继续修改它以使主动管理员与friendly_id一起工作。

配置/初始化/ active_admin.rb:

ActiveAdmin.setup do |config|
  ...

  config.before_filter :revert_friendly_id
end

我在应用程序控制器中定义了revert_friendly_id:

class ApplicationController < ActionController::Base
  ...
  protected

  def revert_friendly_id
    model_name = self.class.name.match(/::(.*)Controller$/)[1].singularize

    # Will throw a NameError if the class does not exist
    Module.const_get model_name

    eval(model_name).class_eval do
      def to_param
        id.to_s
      end
    end
    rescue NameError
  end
end

我注意到当我第一次通过capistrano部署到生产时,友情链接按预期工作。因此,我的产品链接可通过以下网址访问:http://website.com/products/my-product-slug。但是,当我在生产时访问管理界面时,链接会立即切换回产品ID:http://website.com/products/12345。我不完全确定如何解决这个问题,虽然我明白为什么会发生这种情况,有人可以帮助我吗?

4 个答案:

答案 0 :(得分:2)

以下是我解决问题的方法。基于armtrjare在this link的解决方案。

我从应用程序控制器中删除了revert_friendly_id函数,从配置中删除了before_filter。然后将以下内容添加到app / admin / product.rb:

ActiveAdmin.register Product do

  around_filter do |controller, action|
    Product.class_eval do
      alias :__active_admin_to_param :to_param
      def to_param() id.to_s end
    end

    begin
      action.call
    ensure
      Product.class_eval do
        alias :to_param :__active_admin_to_param
      end
    end
  end
...
end

一切都按预期工作。希望这有助于其他人!

答案 1 :(得分:1)

我找到了一个非常简单的解决方案:只需覆盖模型中的to_param并检查它是否是从active_admin调用的。

应用程序/模型/ product.rb:

class Product < ActiveRecord::Base
  def to_param
    if caller.to_s.include?"active_admin"
      id && id.to_s
    else
      slug
    end
  end
end

答案 2 :(得分:0)

设置to_param方法时,将在整个应用程序中设置它。因此,您必须检查所请求的控制器是否在Admin命名空间中。基于此,您必须切换回to_param方法的返回。

答案 3 :(得分:0)

您可以在 get_mut 中重新定义 find_resource 方法:

controller

对于 active_admin controller do def find_resource scoped_collection.friendly.find(params[:id]) end end 关联,您可以使用 belongs_to 选项(来自 https://github.com/activeadmin/inherited_resources/blob/master/lib/inherited_resources/belongs_to_helpers.rb#L17

例如: finder: