質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

1回答

3632閲覧

railsでのタグ機能の実装について

Takumim

総合スコア12

Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

0クリップ

投稿2020/10/22 08:22

お世話になります。

RubyonRailsを使用してアプリを作成しているのですが、タグ機能の実装に苦戦しているため、アドバイスをいただきたいです。
ちなみにgemは使わずに自力で実装しようと思っています。
投稿を(posts)、タグを(tags)としています。中間テーブルを(posts_tags)としています。

#サービス概要
簡易的なSNSアプリで、ユーザーが投稿し、そこに他のユーザーがコメントができるアプリです。

#実現したいこと
ユーザーがタイトル、本文を投稿する際にタグも投稿できるようにしたいです。また、投稿内容を保存し、一覧画面で投稿内容と併せて表示したいです。
ページの遷移としては、posts/new.html.erbで入力→confirm.html.erbで投稿前に内容を確認→index.html.erbで表示という流れです。

#posts/new.html.erb

posts

1 2<h3><strong>New Post</strong></h3> 3<div class="form-group"> 4 <%= form_with(model:@post, local: true, url:posts_confirm_path, class: 'container') do |f| %> 5 <div class="row"> 6 <div class="col-md-5"> 7 <h5><%= f.label :タイトル %></h5> 8 <%= f.text_area :title, autofocus: true, class: "form-control new-post-title" %> 9 </div> 10 </div> 11 <div class="row"> 12 <div class="col-md-8"> 13 <h5><%= f.label :相談内容 %></h5> 14 <%= f.text_area :text, class: "form-control" %> 15 </div> 16 </div> 17 <div class="row"> 18 <div class="col-md-3"> 19 <h5><%= f.label :タグ %></h5> 20 <%= f.text_area :name, class: "form-control" %> 21 </div> 22 </div> 23 <div class="row"> 24 <div class="col-md-1"> 25 <%= f.submit "投稿内容を確認する", class: "new-post-submit" %> 26 </div> 27 </div> 28 <% end %> 29</div>

#posts/confirm.html.erb

posts

1<h3><strong>投稿内容の確認</strong></h3> 2<div class="form-group"> 3 <div class="row"> 4 <div class="col-md-5"> 5 <h5>タイトル</h5> 6 <%= @post.title %> 7 </div> 8 </div> 9 <div class="row"> 10 <div class="col-md-8"> 11 <h5>相談内容</h5> 12 <%= @post.text %> 13 </div> 14 </div> 15 <div class="row"> 16 <div class="col-md-3"> 17 <h5>タグ</h5> 18 <%= @post.tags %> 19 </div> 20 </div> 21 <%= form_with(model: @post, local: true, url: posts_path) do |f| %> 22 <%= f.hidden_field :user_id, value: current_user.id %> 23 <%= f.hidden_field :title %> 24 <%= f.hidden_field :text %> 25 <%= f.hidden_field :name %> 26 <div class="row"> 27 <div class="col-md-1"> 28 <%= link_to "修正する", new_post_path(@post), class: 'btn btn-success' %> 29 </div> 30 </div> 31 <div class="row"> 32 <div class="col-md-1"> 33 <%= f.submit "投稿する", class: 'btn btn-danger' %> 34 </div> 35 </div> 36 <% end %> 37</div> 38 39 40 41 42

#posts_controller

class PostsController < ApplicationController def new @post = Post.new @user = current_user end def confirm @post = Post.new @post.text = params[:post][:text] @post.title = params[:post][:title] end def create @post = Post.tags.create(post_params) @post.save redirect_to posts_path end def index @posts = Post.all end def show @post = Post.find(params[:id]) @post_comment = PostComment.new @post_comments = @post.post_comments.order(created_at: :desc) end def destroy post = Post.find(params[:id]) post.destroy end private def post_params params.require(:post).permit(:user_id, :title, :text) end end

#tags_controller

class TagsController < ApplicationController def create @post = current_post @tag = @post.tags.build(tag_params) @tag.save end private def tag_params params.require(:tag).permit(:name) end end

#post.rb

class Post < ApplicationRecord belongs_to :user, optional: true has_many :post_comments, dependent: :destroy has_many :likes, dependent: :destroy has_many :post_tags, dependent: :destroy has_many :tags, through: :post_tags, dependent: :destroy validates :text, presence: true, length: { maximum: 30 } def liked_by?(user) likes.where(user_id: user.id).exists? end end

#post_tag.rb

class PostTag < ApplicationRecord belongs_to :post belongs_to :tag end

#tag.rb

class Tag < ApplicationRecord has_many :post_tags, dependent: :destroy has_many :posts, through: :post_tags, dependent: :destroy end

#routes.rb

Rails.application.routes.draw do root "homes#top" devise_for :admin_users, ActiveAdmin::Devise.config ActiveAdmin.routes(self) devise_for :users, controllers:{ sessions: "devise/sessions", registrations: "devise/registrations" } post 'posts/confirm' => 'posts#confirm' resources :posts, only:[:index, :new, :create, :edit, :update, :show, :destroy] do resource :likes, only:[:create, :destroy] resource :post_comments, only:[:create] end delete "posts/:post_id/post_comments/:post_comment_id", to: "post_comments#destroy", as: :post_comment resource :tags, only:[:create, :destroy] resources :users, only:[:show, :edit, :update] # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html post "/home/guest_sign_in" => "homes#new_guest" end

#schema.rb

# This file is auto-generated from the current state of the database. Instead # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. # # Note that this schema.rb definition is the authoritative source for your # database schema. If you need to create the application database on another # system, you should be using db:schema:load, not running all the migrations # from scratch. The latter is a flawed and unsustainable approach (the more migrations # you'll amass, the slower it'll run and the greater likelihood for issues). # # It's strongly recommended that you check this file into your version control system. ActiveRecord::Schema.define(version: 2020_10_22_021900) do create_table "active_admin_comments", force: :cascade do |t| t.string "namespace" t.text "body" t.string "resource_type" t.integer "resource_id" t.string "author_type" t.integer "author_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["author_type", "author_id"], name: "index_active_admin_comments_on_author_type_and_author_id" t.index ["namespace"], name: "index_active_admin_comments_on_namespace" t.index ["resource_type", "resource_id"], name: "index_active_admin_comments_on_resource_type_and_resource_id" end create_table "admin_users", force: :cascade do |t| t.string "email", default: "", null: false t.string "encrypted_password", default: "", null: false t.string "reset_password_token" t.datetime "reset_password_sent_at" t.datetime "remember_created_at" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["email"], name: "index_admin_users_on_email", unique: true t.index ["reset_password_token"], name: "index_admin_users_on_reset_password_token", unique: true end create_table "empathies", force: :cascade do |t| t.integer "post_id" t.integer "user_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false end create_table "likes", force: :cascade do |t| t.integer "user_id" t.integer "post_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false end create_table "post_comments", force: :cascade do |t| t.integer "user_id" t.integer "post_id" t.string "text" t.datetime "created_at", null: false t.datetime "updated_at", null: false end create_table "posts", force: :cascade do |t| t.integer "user_id" t.string "text" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "title" end create_table "posts_tags", force: :cascade do |t| t.integer "post_id" t.integer "tag_id" end create_table "tags", force: :cascade do |t| t.integer "post_id" t.string "name" t.datetime "created_at", null: false t.datetime "updated_at", null: false end create_table "thanks", force: :cascade do |t| t.integer "user_id" t.integer "comment_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false end create_table "users", force: :cascade do |t| t.string "email", default: "", null: false t.string "encrypted_password", default: "", null: false t.string "reset_password_token" t.datetime "reset_password_sent_at" t.datetime "remember_created_at" t.string "name" t.text "introduction" t.string "profile_image_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["email"], name: "index_users_on_email", unique: true t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true end end

#疑問点
◉投稿とタグは多対多の関係だと思うので、中間テーブルを作成(posts_tags)し、リレーションを組んだのですが、ルーティングに関してはネストさせる必要はあるのでしょうか。

◉tagのカラム(:name)をnew.html.erbに記述し、confirm.html.erbに移動すると、
:titleと:textは表示されるのですが、

<Tag::ActiveRecord_Associations_CollectionProxy:0x0000000005eda080>

と表示されてしまいます。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

「ルーティングに関してはネストさせる必要はあるのでしょうか」
しなくてもできます

Tag::ActiveRecord_Associations_CollectionProxy:0x0000000005eda080
と表示されてしまいます。」

@post.tags は復数ある(かもな)ので loopで回してください
<% @post.tags.each do |tag| %> <%= ここでtagを表示 %> <%end%> ですね。

投稿2020/10/22 13:32

winterboum

総合スコア23324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Takumim

2020/10/22 14:58

ありがとうございます、表示できました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問