Реализация тегов в Rails: как ссылаться на несколько элементов одним тегом? - PullRequest
5 голосов
/ 11 августа 2011

Я пишу движок блога в rails и настроил модель тега и модель поста, которые имеют отношение have_and_belongs_to_many. Добавление тегов работает нормально, проблема возникает при поиске всех сообщений с определенным тегом:

Если я добавлю тег «test» к сообщению A, а затем добавлю тег «test» к сообщению B, появятся два объекта тега, оба с именем «test», но с разными идентификаторами, оба ссылаются на разные сообщения. Теперь, если у меня есть действие контроллера indexTagPosts, которое принимает параметр «тег» и находит все сообщения с этим тегом, он вернет только одно сообщение, поскольку другой тег имеет другой идентификатор и на самом деле не связан. Должен ли я каким-то образом ограничивать добавление новых тегов или манипулировать тем, как я по-разному извлекаю все соответствующие теги?

Вот действие контроллера, которое должно захватывать все соответствующие сообщения на основе параметра 'tag':

def indexTagPosts

        @tag = Tag.find(params[:tag])
        @posts = @tag.posts.all

end

А вот действие по сохранению тега:

def create


    @post = Post.find(params[:post_id])
    @tag = @post.tags.create(params[:tag])

    respond_to do |format|
      if @tag.save
        format.html { redirect_to edit_post_path(@post),:notice => "Success" }
      end
    end  

end

Заранее благодарим и приносим извинения за избыточность или неправильную формулировку.

1 Ответ

9 голосов
/ 11 августа 2011

Хотелось бы знать, откуда у всех появилась идея использовать has_and_belongs_to_many, потому что управлять этим действительно сложно, даже если в начале это кажется простым.Лучшим подходом является наличие отношения типа has_many ..., :through, потому что вы можете управлять отдельными ссылками и легко добавлять к ним метаданные.

Например, вот простое двустороннее соединение с промежуточной моделью:шаблон, который вы найдете, встречается довольно часто:

class Post < ActiveRecord::Base
  has_many :post_tags
  has_many :tags, :through => :post_tags
end

class Tag < ActiveRecord::Base
  has_many :post_tags
  has_many :posts, :through => :post_tags
end

class PostTag < ActiveRecord::Base
  belongs_to :post
  belongs_to :tag
end

Добавление и удаление ссылок тегов на этом этапе тривиально:

@post = Post.find(params[:post_id])

if (params[:tags].present?)
  @post.tags = Tag.where(:name => params[:tags].split(/\s*,\s*/))
else
  @post.tags = [ ]
end

Менеджер отношений has_many создаст, обновит илипри необходимости уничтожьте PostTag модели ассоциаций.

Как правило, вы развиваете модель Post, чтобы включить вспомогательный метод для извлечения и назначения тегов с использованием любого разделителя, который вам нравится:

 class Post
   def tags_used
     self.tags.collect(&:name).join(',')
   end

   def tags_used=(list)
     self.tags = list.present? ? Tag.where(:name => list.split(/\s*,\s*/)) : [ ]
   end
 end
...