【问题标题】:Adding Tags in Rails在 Rails 中添加标签
【发布时间】:2015-09-07 07:07:23
【问题描述】:

添加标签,我得到这个错误

SQLite3::SQLException:没有这样的列:taggings.available_work_id: SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."available_work_id" = ?

Available_work.index.html

    <tbody>
    <% @available_works.each do |available_work| %>
      <tr>
        <td><%= available_work.title %></td>
        <td><%= available_work.description.html_safe %></td>
        <td>Tags: <%= raw available_work.tags.map(&:name).map { |t| link_to t, tag_path(t) }.join(', ') %></td>
        <td><%= image_tag available_work.image_url(:thumb) %></td>
        <td><%= link_to 'Show', available_work %></td>
        <td><%= link_to 'Edit', edit_available_work_path(available_work) %></td>
        <td><%= link_to 'Destroy', available_work, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
    </tbody>
   </table>

Available_work.rb

 class AvailableWork < ActiveRecord::Base
    attr_accessor :image, :remote_image_url, :tag_list
    mount_uploader :image, ImageUploader
    has_many :taggings
    has_many :tags, through: :taggings


    def self.tagged_with(name)
      Tag.find_by_name!(name).available_work
    end

    def self.tag_counts
      Tag.select("tags.*, count(taggings.tag_id) as count").
        joins(:taggings).group("taggings.tag_id")
    end

    def tag_list
      tags.map(&:name).join(", ")
    end

    def tag_list=(names)
      self.tags = names.split(",").map do |n|
        Tag.where(name: n.strip).first_or_create!
      end
    end
    end

标签.rb

 class Tag < ActiveRecord::Base
 has_many :taggings
 has_many :available_work, through: :taggings
 end

标签.rb

 class Tagging < ActiveRecord::Base
 belongs_to :tag
 belongs_to :availble_work
 end

架构

create_table "available_works", force: :cascade do |t|
    t.string   "title"
    t.string   "description"
    t.string   "tags"
    t.string   "image"
    t.datetime "created_at",  null: false
    t.datetime "updated_at",  null: false
    t.string   "taggings"
    end

【问题讨论】:

    标签: ruby-on-rails tags


    【解决方案1】:

    您必须在标记表中添加一个available_work_id 列。不过,创建与标记对象的多态关系可能会更好,这样您就可以将标记用于比AvailableWork 模型更多的用途。

    已编辑。我的例子中有几个错误。这是一个完整的运行版本:

    class Tag < ActiveRecord::Base
      has_many :taggings
    
      def self.tag_counts
        select("tags.*, count(taggings.tag_id) as count")
          .joins(:taggings)
          .group("taggings.tag_id")
       end
    end
    

    class Tagging < ActiveRecord::Base
      belongs_to :tag
      belongs_to :tagged,
                 polymorphic: :true,
                 inverse_of: :taggings
    end
    

    class AvailableWork < ActiveRecord::Base
      has_many :taggings, as: :tagged
      has_many :tags, through: :taggings
    
      def self.tagged_with(name)
        # We have to do this in two queries since Rails does not
        # do joins on polymorphic relations.
        ids = Tagging.where(tagged_type: self.name)
               .joins(:tag)
               .where(tags: { name: name }).pluck(:tagged_id)
        find(ids)
      end
    
      def self.tag_counts
        Tag.tag_counts.where(taggings: { tagged_type: self.name  })
      end
    
      def tag_list
        tags.map(&:name).join(", ")
      end
    
      def tag_list=(names)
        self.tags = names.split(",").map do |n|
          Tag.where(name: n.strip).first_or_create!
        end
      end
    end
    

    ActiveRecord::Schema.define(version: 20150621234032) do
      create_table "available_works", force: :cascade do |t|
        t.string   "title"
        t.string   "description"
        t.string   "image"
        t.datetime "created_at",  null: false
        t.datetime "updated_at",  null: false
      end
    
      create_table "taggings", force: :cascade do |t|
        t.integer  "tag_id"
        t.integer  "tagged_id"
        t.string   "tagged_type"
        t.datetime "created_at",  null: false
        t.datetime "updated_at",  null: false
      end
    
      add_index "taggings", ["tag_id"], name: "index_taggings_on_tag_id"
      add_index "taggings", ["tagged_id"], name: "index_taggings_on_tagged_id"
    
      create_table "tags", force: :cascade do |t|
        t.string   "name"
        t.datetime "created_at", null: false
        t.datetime "updated_at", null: false
      end
    end
    

    <table>
      <tbody>
      <% @available_works.each do |available_work| %>
        <tr>
          <td><%= available_work.title %></td>
          <td><%= available_work.description.try(:html_safe) %></td>
          <td>Tags: <%= available_work.tag_list %></td>
          <td><%#= image_tag available_work.image_url(:thumb) %></td>
          <td><%= link_to 'Show', available_work %></td>
          <td><%= link_to 'Edit', edit_available_work_path(available_work) %></td>
          <td><%= link_to 'Destroy', available_work, method: :delete, data: { confirm: 'Are you sure?' } %></td>
        </tr>
      <% end %>
      </tbody>
    </table>
    

    请注意,我已将图片部分注释掉以节省时间,因为它与问题没有直接关系。

    我为回答这个问题而创建的 Rails 应用程序位于 https://github.com/maxcal/playground/tree/adding-tags-in-rails

    【讨论】:

    • 感谢您的帮助@maxcal .. 我听从了您的建议,但收到错误消息。 undefined method tag_list' for nil:NilClass 标签:
    • 您是否只是将我的答案中的 AvailableWork 类直接复制/粘贴到您的应用中?
    • 除了AvailableWork类
    • 我从未创建过多态实体
    • DANG .. 你写了这么多代码。感谢您的帮助。我将不得不研究多态性。而且您的应用确实有效。
    猜你喜欢
    • 1970-01-01
    • 2017-02-16
    • 2011-01-04
    • 2012-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多