使用acts_as_taggable_on为标记创建url slugs

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

在我自己创建的模型中,我通常通过覆盖模型的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并自定义它,如果有任何方法我可以使用我自己的应用程序代码。 谢谢。

我正在使用friendly_id( https://github.com/norman/friendly_id )gem来管理slug。 我为我的标签创建slugs的方法与你的类似,但更简单一点。

我刚刚使用以下代码创建了初始化程序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') #=> # ActsAsTaggableOn::Tag.find('im-a-ruby-programmer') #=> # 

希望这有帮助……

@ 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列称为永久链接 ,如果您愿意,可以使用slugged 。 顺便说一句,我使用以下内容:

  • friendly_id(4.0.5)
  • act-as-taggable-on(2.2.2)

感谢Vitork的初始代码!

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

сonfig/初始化/ 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 4.x,friendly_id 5.x),请执行以下步骤:

创建迁移以将slug添加到tags表

 # 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 ActsAsTaggableOn::Tag.friendly.find 'tag-name'添加到friendly_id:使用call直接在模型上使用find。 在friendly_id指南中阅读更多内容。

还有另一种方式。

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

 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这样的url获取所有条目


用法视图:

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