shunta9922
@shunta9922 (shimo shun)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

インクリメンタル検索

解決したいこと

Ruby on RailsでtwitterのようなWebアプリをつくり、インクリメンタル検索を実装しています。
投稿した記事(movie)と投稿したユーザーをajaxで取得し表示する際にエラーが発生しました。

発生している問題・エラー

NoMethodError: undefined method `user' for #<Movie::ActiveRecord_Relation:0x000000000a7337a0>
Did you mean?  super
from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-5.2.5/lib/active_record/relation/delegation.rb:125:in `method_missing'

movie.model

class Movie < ApplicationRecord
    validates :content, {presence: true, length: {maximum: 1000}}
    validates :user_id,{presence: true}
    def user 
        return User.find_by(id: self.user_id)
    end

    def self.search(search)
        return put "見つかりませんでした" unless search
        Movie.where(['content LIKE?',"%#{search}%"])
    end

    has_many :comment,foreign_key: :reply_comment,dependent: :destroy
    belongs_to :user

end

movie.js

$(document).on('turbolinks:load',function(){
 $(function () {
  $('.js-text_field').on('keyup', function () {
    var content = $.trim($(this).val());
    $.ajax({
      type: 'GET', 
      url: '/movies/search',
      data:  {content: content}, 
      dataType: 'json' 
    })
     .done(function(data){
      $('.js-movie-indexes').empty();
      $(data).each(function(user,movie) {
      $('.js-movie-indexes').append(
        `
        <img src="/user_images/${user.image_name}">
        <p href="/users/${user.id}">${user.id}</p>
        <p>${movie.title}</p>
        <p href="/movies/${movie.id}">${movie.content}</p>
         '
      );
      });
     })

     .fail(function(){
       console.log('通信に失敗しました');
     })
  });
 });
});

movies_controller

def search
   @movie = Movie.search(params[:content])
   @user = @movie.user

   respond_to do |format|
    format.html {redirect_to :root}
    format.json {render json:[@movie,@user]}
   end

  end

routes

 search_movies GET    /movies/search(.:format)
movies#search {:format=>:json}

index.html.erb

<%= form_with(url:movies_searches_path,:method => 'get') do |f| %>
         <%= f.text_field :search,id:'search' ,class: 'js-text_field'%> 
         <%= f.submit "検索", :name => nil %>        
     <%end%>
0

1Answer

NoMethodError: undefined method `user' for #<Movie::ActiveRecord_Relation:0x000000000a7337a0>

ActiveRecord_Relationには.userというメソッドはない

def search
   # movieはゼロから複数返ってくることが想定される
   # なので@moviesの方が分かりやすい(複数形)
   # p @movie.class としてみれば分かるが実体はActiveRecord_Relation
   # [Movie, Movie, Movie]というような配列のイメージ(違うけど)
   @movie = Movie.search(params[:content]) # searchは.whereをしてる
   @user = @movie.user # Movieモデルではないので、.userは無い
    def self.search(search)
        return put "見つかりませんでした" unless search
        Movie.where(['content LIKE?',"%#{search}%"]) # 実体はActiveRecord_Relation
    end

Movieが[いちUser](単数形)と関連があるなら、普通はbelongs_toを使う。

class Movie < ApplicationRecord
    validates :content, {presence: true, length: {maximum: 1000}}
    validates :user_id,{presence: true}
    def user 
        return User.find_by(id: self.user_id)
    end
0Like

Comments

  1. @shunta9922

    Questioner

    いつも返信して頂きありがとうございます。
    @user = @movie.user # Movieモデルではないので、.userは無い"
    が理解できません。
    ・userメソッドがtiveRecord_Relationのメソッドにはないからエラー
    ・modelにあるsearchメソッドは.whereを使っているから、ActiveRecord_Relationのメソッドである
    上二つは理解できたのですがuserメソッドもfind_byをつかっているのでuserメソッドもActiveRecord_Relationのメソッドと思っているのですがどう違うのでしょうか?
  2. Movie.where(...).user

    と出来るかどうか?でわかりますか?
  3. @shunta9922

    Questioner

    えっと..
    movie.where(..)はモデル.activerecordメソッドで出来るが、
    userメソッドはインスタンスメソッドでインスタンスがないから結果としてMovie.where(...).userは出来ないで間違いないですか?
  4. @shunta9922

    Questioner

    おっしゃるように Movie.where(...).first.userと記述してみたら、検索ワードで投稿したユーザーのレコードを取得することができました。しかし、firstメソッドをしようすることで取得できることが未だ腑に落ちません。お手数ですが解説して頂けないでしょうか?
  5. MovieはActive Recordのサブクラスです。この辺の理解がないと何をやってるのかわからないと思います。

    Railsはライブラリとしては膨大なので一つ一つ聞いていたら次のメジャーバージョンがでてしまうので、

    https://railsguides.jp/active_record_basics.html
    ここの辺りを全部読んで理解するのが早いと思います。

  6. @shunta9922

    Questioner

    ご返信ありがとうございます。頑張って理解します。

Your answer might help someone💌