tag機能の実装(テーブル作成)
- 多対多のテーブルを作成
- ドキュメントをタグ付きで追加するAPIの作成
多対多テーブルの作成
モデルの作成
rails generate model tag name:string
中間テーブルの作成
rails generate model document_tag document:reference tag:reference
マイグレート
rake db:migrate
関係をモデルのファイルに記述
models/document.rb
class Document < ActiveRecord::Base
has_many :document_tags
has_many :tags, through: :document_tags
...
end
models/tag.rb
class Tag < ActiveRecord::Base
has_many :document_tags
has_many :documents, through: :document_tags
...
end
models/document_tag.rb
class DocumentTag < ActiveRecord::Base
belongs_to :document
belongs_to :tag
...
end
これにてテーブルの作成は終了。。。簡単?ですね
ドキュメントをタグ付きで追加するAPIの作成
以前作成したdocument_api.rbを編集
document_api.rb
class Document_API < Grape::API
resource "documents" do
helpers do
...
def save_tags(document,tag_name)
tag = Tag.where(name: tag_name).first_or_create()
table_obj = DocumentTag.new(tag_id: tag.id, document_id: document.id)
table_obj.save
# tag = Tag.find_by(name: tag_name)
# unless tag
# tag_obj = Tag.new(name: tag_name)
# tag_obj.save
# table_obj = DocumentTag.new(tag_id: tag_obj.id, document_id: document.id)
# table_obj.save
# else
# table_obj = DocumentTag.new(tag_id: tag.id, document_id: document.id)
# table_obj.save
# end
end
end
...
desc "create a document"
params do
requires :content, type: String
requires :title, type: String
requires :user_id, type: Integer
optional :tags, type: Array
end
# http://localhost:3000/api/document
post do
document = Document.new(document_params)
if document.save
params[:tags].each do |tag_name|
save_tags(document,tag_name)
end
else
...
end
end
...
end
end
helperのsave_tagsは同一名のものがもうすでにあればそのIDと作成したドキュメントのIDを中間テーブルに保存し、タグが存在しなければそのタグを作成した後中間テーブルにそれぞれのIDを保存しています
とても汚いと思うのですが何かいい案があれば教えていただければ幸いです
first_or_createを用いるとある程度キレイにできましたがユニークにして否応なしに保存すればいいのでは?という疑問
どちらが軽いとかあるのでしょうか?