【问题标题】:Creating url slugs for tags with acts_as_taggable_on使用acts_as_taggable_on 为标签创建url slug
【发布时间】:2011-06-26 08:06:52
【问题描述】:

我想为acts_as_taggable_on gem 管理的标签创建url slug。例如,我想要http://myapp.com/tags/my-tag(其中“我的标签”是标签的唯一名称),而不是像http://myapp.com/tags/5 这样的网址。

在我自己创建的模型中,我通常通过覆盖模型的 to_param 方法并在模型中创建一个“slug”字段来保存新的 to_param 方法的结果。我尝试使用 ActsAsTaggableOn 的 Tag 模型来执行此操作,但它不起作用。

否则我可以覆盖 ActsAsTaggableOn 的 tag.rb 类中的内容,如下所示:

# Overwrite tag class
ActsAsTaggableOn::Tag.class_eval do
  def name
    n = read_attribute(:name).split
    n.each {|word| word.capitalize!}.join(" ")
  end      
end

但是,如果我尝试使用以下方法定义覆盖同一块中的 to_param 方法:

def to_param
  name.parameterize
end

Rails 仍然使用整数 ID 而不是参数化名称生成和响应路由。事实上,如果我尝试类似的东西在控制台中

ActsAsTaggableOn::Tag.find(1).to_param

返回整数 ID,而不是被覆盖的 to_param 方法的结果。

如果有任何方法可以使用我自己的应用程序代码来完成,我宁愿不分叉 gem 并对其进行自定义。谢谢。

【问题讨论】:

    标签: ruby-on-rails acts-as-taggable-on


    【解决方案1】:

    我正在使用friendly_id (https://github.com/norman/friendly_id) gem 来管理蛞蝓。我为标签创建 slug 的方法与您的类似,但稍微简单一些。

    我刚刚使用以下代码创建了初始化程序 act_as_taggable_on.rb:

    # act_as_taggable_on.rb
    ActsAsTaggableOn::Tag.class_eval do
      has_friendly_id :name,
                      :use_slug => true,
                      :approximate_ascii => true,
                      :reserved_words => ['show', 'edit', 'create', 'update', 'destroy']
    end
    

    然后:

    @user = User.new :name => "Jamie Forrest"
    @user.tag_list = "This is awesome!, I'm a ruby programmer"
    @user.save
    

    然后瞧:

    ActsAsTaggableOn::Tag.find('this-is-awesome')    #=> #<Tag id: 1, name: "This is awesome!">
    ActsAsTaggableOn::Tag.find('im-a-ruby-programmer')    #=> #<Tag id: 2, name: "I'm a ruby programmer">
    

    希望对您有所帮助...

    【讨论】:

      【解决方案2】:

      @vitork 的代码是一个好的开始,但不适用于新版本的friendly_id 和acts_as_taggable。这是一个更新的初始化程序:

      ActsAsTaggableOn::Tag.class_eval do
      extend FriendlyId
      friendly_id :name,
                    :use => :slugged,
                    :slug_column => :permalink,
                    :reserved_words => ['show', 'edit', 'create', 'update', 'destroy']
      end
      

      我的 db 列名为 permalink,如果您愿意,可以使用 slugged。顺便说一句,我正在使用以下内容:

      • friendly_id (4.0.5)
      • 作为可标记的 (2.2.2)

      感谢 Vitork 提供初始代码!

      【讨论】:

        【解决方案3】:

        要使其与最新版本(Rails 4.x,friendly_id 5.x)一起工作,您应该遵循以下步骤:

        创建迁移以将 slug 添加到标签表

        # rails generate migration add_slugs_to_tags
        class AddSlugToTags < ActiveRecord::Migration
          def change
            add_column :tags, :slug, :string
            add_index :tags, :slug
          end
        end
        

        您可以重命名 :slug 列 - 如果您更改它,您应该在初始化程序中指定列名。不要忘记运行迁移rake db:migrate

        为 ActsAsTaggableOn 创建一个初始化器

        # config/initializers/acts_as_taggable_on.rb
        ActsAsTaggableOn::Tag.class_eval do
          extend FriendlyId
        
          friendly_id :name, use: :slugged
        end
        

        搜索标签时,您必须使用ActsAsTaggableOn::Tag.friendly.find 'tag-name' 或将:finders 添加到friendly_id :使用调用直接在模型上使用find。在friendly_id guides 中阅读更多内容。

        【讨论】:

          【解决方案4】:

          实际上答案要简单得多,您不需要使用friendly_id 或任何其他不必要的扩展。

          сconfig/initializers/act_as_taggable_on.rb

          ActsAsTaggableOn::Tag.class_eval do
            before_save { |tag| tag.slug = name.parameterize if name_changed? }
          
            def to_param
              slug
            end
          end
          

          如果需要,添加一个 slug 列,否则跳过 before_save 回调。

          然后在视图中,而不是像这样迭代

          article.tag_list.each do |tag|..
          

          你会这样迭代

          article.tags.each
          

          因为 tag_list 只给你字符串,而使用标签你有真正的标签实例。 至少在控制器中

          if params[:tag]
             tag = ActsAsTaggableOn::Tag.find_by_slug(params[:tag])
             @articles = Article.moderated.includes(:user).tagged_with(tag)
          end
          

          【讨论】:

          • 太棒了。正是我想要的
          • 这甚至适用于 Rails 5 和 act_as_taggable_on v4
          【解决方案5】:

          还有另一种方法。

          使用单个操作为标签创建控制器:

          rails g controller tags index
          

          routes.rb 中将生成的路由更改为:

          get 'tags/:tag' => 'tags#index', as: :tag
          

          tags_controller.rb 中添加以下代码:

          def index
              @tag = params[:tag]
              @entries = Entry.tagged_with(@tag)
          end
          

          其中Entry 是型号名称。

          现在您可以获取所有带有漂亮网址的条目,例如 example.com/tags/animals


          在视图中的使用:

          - @entry.tags.each do |tag|
            = link_to tag, tag_path(tag.name)
          

          【讨论】:

            猜你喜欢
            • 2012-04-30
            • 1970-01-01
            • 2020-05-24
            • 1970-01-01
            • 2014-06-07
            • 2011-04-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多