前提・実現したいこと
ActionTextを使用して投稿した記事の検索をして文章だけを一覧表示したい。
今回は検索の結果をBootstrapのCard機能をしようして一覧表示にしたいので、画像のデータがあるとレイアウトが崩れてしまいます。
発生している問題・エラーメッセージ
なんとかActionText内のデータを検索することには成功し、表示させることには成功したのですが,挙動が少しおかしいです。
エラーの発生条件
- サーバーを再起動した後にトップ画面(URL:localhost:3000)を再読み込み後、検索フォームに何か文字を入力してから検索ボタンを押すと
Showing /Users/masakikengo/projects/tiisana/app/views/posts/search.html.erb where line #6 raised: undefined method `each' for :search:Symbol
とエラーが表示される。
-
ただ何も入力せずに検索ボタンだけを押してもエラーは出ずに画面遷移だけ行われ、その後に検索してもエラーは発生しない。
-
エラー発生後に同じ画面を再読み込みするとその後の検索では問題無く記事の内容は検索できるようになる。
-
ログイン状態はエラーの発生には関係がない。
検索結果を表示するactionのcode
app/controllers/posts_controller.erb
def search @posts = Post.search(params[:keyword]) end
app/models/post.rb
class Post < ApplicationRecord ##省略## def self.search(search) if search != "" scope :search, -> (search_param = nil) { return if search_param.blank? joins("INNER JOIN action_text_rich_texts ON action_text_rich_texts.record_id = posts.id AND action_text_rich_texts.record_type = 'Post'") .where("action_text_rich_texts.body LIKE ? OR posts.title LIKE ? ", "%#{search_param}%", "%#{search_param}%") } else Post.all end end
なにぶん初心者なので細かい部分の動きの理解が乏しくて中々自分で調べているだけでは原因にたどり着けませんでした。
該当のソースコード
app/models/post.rb
class Post < ApplicationRecord has_rich_text :content has_one_attac hed :image belongs_to :user has_many :comments validates :title, presence: true, length: { minimum: 3 } validates :image, :content, presence: true validates :title, presence: true validates :content, presence: true def self.search(search) if search != "" scope :search, -> (search_param = nil) { return if search_param.blank? joins("INNER JOIN action_text_rich_texts ON action_text_rich_texts.record_id = posts.id AND action_text_rich_texts.record_type = 'Post'") .where("action_text_rich_texts.body LIKE ? OR posts.title LIKE ? ", "%#{search_param}%", "%#{search_param}%") } else Post.all end end end
app/controllers/posts_controller.erb
class PostsController < ApplicationController before_action :set_post, only: [:show, :edit, :update, :destroy] before_action :move_to_index, except: [:index, :show, :search] def index @posts = Post.includes(:user).order("created_at DESC") end def show @post = Post.find(params[:id]) @comment = Comment.new @comments = @post.comments.includes(:user).order("created_at DESC") end def new @post = Post.new end def edit end def create @post = Post.new(post_params) respond_to do |format| if @post.save format.html { redirect_to @post, notice: 'Post was successfully created.' } format.json { render :show, status: :created, location: @post } else format.html { render :new } format.json { render json: @post.errors, status: :unprocessable_entity } end end end def update respond_to do |format| if @post.update(post_params) format.html { redirect_to @post, notice: 'Post was successfully updated.' } format.json { render :show, status: :ok, location: @post } else format.html { render :edit } format.json { render json: @post.errors, status: :unprocessable_entity } end end end def destroy @post.destroy respond_to do |format| format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' } format.json { head :no_content } end end def search @posts = Post.search(params[:keyword]) end private def set_post @post = Post.find(params[:id]) end def post_params params.require(:post).permit(:title, :content, :image).merge(user_id: current_user.id) end def move_to_index unless user_signed_in? redirect_to action: :index end end end
app/views/posts/search.html.rb
<div class="container" style="margin-top:100px;"> <div class="album py-5 bg-light"> <div class="container "> <div class="row"> <% @posts.each do |post| %> <div class="col-md-4"> <div class="card text-center"> <td><%= image_tag post.image.variant(resize:'200x200'), class: "card-img-top" %></td> <h4 class="card-text"><%= post.title %></h4> <div class="card-body"> <%= strip_tags(post.content.to_s).gsub(/[\n]/,"").strip.truncate(10)%> <div class="d-flex justify-content-between align-items-center"> <div class="btn-group mt-3 mx-auto"> <% if user_signed_in? && current_user.id == post. user_id%> <%= link_to '編集', edit_post_path(post), class: "btn btn-sm btn-outline-primary" %> <%= link_to '削除', post, method: :delete, data: { confirm: 'Are you sure?' } , class: "btn btn-sm btn-outline-primary"%> <% else %> <%= link_to '詳細', post, class: "btn btn-sm btn-outline-primary" %> <%= link_to 'トップページ', posts_path, class: "btn btn-sm btn-outline-primary" %> <% end %> </div> </div> <small class="text-muted mt-4"><%= post.created_at.to_s(:datetime_jp) %></small> </div> </div> </div> <% end %> </div> </div> </div> <div class="container" style="margin-bottom:100px;">
###追加のコード
app/views/layouts/application.html.erb
<body> <nav class="navbar navbar-light navbar-expand-md "> <a class="navbar-brand text-primary",class="h1" href="/"> <div class="h3">Tiisana</div> </a> <div class="collapse navbar-collapse"> <ul class="navbar-nav ml-auto"> <div class="navbar-item d-flex justify-content-end align-items-center"> <%= form_with(url: search_posts_path, local: true, method: :get, class: "search-form") do |form| %> <div class="input-group"> <%= form.text_field :keyword, class: "search-form navop" %> <%= button_tag sanitize('<i class="fa fa-search"></i>'), :type => "submit",:class =>"btn btn-light mr-1" %> </div> </div> <% end %> <% if user_signed_in? %> <li class="nav-item mr-2 "> <%= link_to "新規投稿", new_post_path, class: "nav-alink btn btn-light " %> </li> <li class="nav-item dropdown"> <div class="btn-group"> <button class="nav-alink btn btn-light dropdown-toggle" data-toggle="dropdown" href="/" aria-haspopup="true" aria-expanded="false"><%= current_user.nickname %> </button> <div class="dropdown-menu dropdown-menu-right"> <%= link_to "マイページ", "/users/#{current_user.id}", class: "dropdown-item", type:"button"%> <%= link_to "ログアウト", destroy_user_session_path, method: :delete, class:"dropdown-item", type:"button"%> </div> </div> <ul> </li> <% else %> <li class="nav-item mr-2"> <%= link_to "ログイン", new_user_session_path, class: "nav-alink btn btn-light" %> <%= link_to "新規登録", new_user_registration_path, class: "nav-alink btn btn-light"%> </li> </ul> <% end %> </div> </nav> <%= yield %> <nav class="navbar bg-light navbar-light navbar-expand-md mt-5 fixed-bottom"> <a class="navbar-brand text-center" href="/">© 2020 Tiisana</a> </nav> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script> </body>
試したこと
エラー分の内容的にeach文の中に渡している値がおかしいみたいのなので、ActionTextの内容を表示させる以下の部分を
<%= strip_tags(post.content.to_s).gsub(/[\n]/,"").strip.truncate(10)%>
以下に変更すると
<%= post.content %>
確かに投稿した内容は全て表示される。
検索機能と検索後に文章だけを抜粋するのは以下のサイトを参考に実装しました。
Rails6のActionTextでransackがうまく使えないので検索できるようにする
ActionText で truncate を使って文章を抜粋する
何度か記事を読み返して自分なりにコードをいじってみましたが解決できませんでした。
まだ質問に慣れていないので分かりにくい点も多いと思いますが、原因を教えていただけると非常に嬉しいです。
どうかよろしくおねがいします。
補足情報(FW/ツールのバージョンなど)
ruby_version 2.6.5
Rails 6.0.3.4
Bootstrap 4.1.1
回答1件
あなたの回答
tips
プレビュー