[Rails] where의 반환값에 대한 이야기를 주의하세요.

8702 단어 초학자RubyRails

개시하다


왜 썼어요?

  • where와pluck의 반환값을 이해하지 못하고 만재 경험을 공유
  • ".id 되겠지", 액티브 레코드 남용에 대한 반성의 뜻
  • 결론


  • where 또는 pluck의 반환값은 수조→pluck은 수조로 반환
  • where 반환Active Record::Relation ※ 추기 20/11/10
  • ActiveRecord를 이해하는 방법 검사의 사용처
  • 전제 조건


    컨디션


    ・Rubby 2.6.5
    ・Rails6.0.3
    • devise(user 모델) 사용

    ER 그림



    rooms 테이블:DM 룸 관리
    user_rooms 테이블:user와 room의 조합을 관리합니다

    하고 싶은 일



    그림은userrooms 책상입니다.
    <하고 싶은 일>
    DM 객체(id=10)에 대한 사용자 정보를 얻으려고 합니다.
    < 조건 >
    DM의 룸room_id: 2자신(current user)은 user_id: 15

    이벤트


    다음 코드로 실현하려고 시도합니다
    rooms_controller.rb
    class RoomsController < ApplicationController
      def show
          @room = Room.find(params[:id])
          current_user_room = @room.user_rooms.where.not(user_id: current_user.id)
          user_id = current_user_room.user_id
          @user = User.find(user_id)
      end
    end
    
    세 번째 줄: 두 사용자가 참가한 것을 정의합니다@room(id:2).
    4행: @room.user_rooms에서 @room와 사용자의 조합을 얻는다.(이때 기록은 두 개로 압축됩니다.)그리고 where.not(user_id: current_user.id)에서 기록을 자신을 포함하지 않는 기록으로 축소한다.
    다섯 번째 줄: 네 번째 줄에서 얻은 기록 중,userid를 얻으려고 합니다.
    단, 4 줄은 다음과 같은 오류가 발생합니다.
    [*] pry(main)> current_user_room.user_id
    
    # 結果
    NoMethodError: undefined method `user_id' for #<UserRoom::ActiveRecord_AssociationRelation:0x00007fbef39437e8>
    
    ???
    한마디로 출력current_user_room
    [**] pry(main)> current_user_room
    
    # 結果
    => [#<UserRoom:0x00007fbeefb36518
      id: 2,
      user_id: 10,
      room_id: 2,
      created_at: Sat, 07 Nov 2020 04:00:28 UTC +00:00,
      updated_at: Sat, 07 Nov 2020 04:00:28 UTC +00:00>]
    
    
    왜 못하지?id=2find를 사용하여 획득
    [**] pry(main)> user_room1 = UserRoom.find(2)
    
    # 結果
    => #<UserRoom:0x00007fbeec46c960
     id: 2,
     user_id: 10,
     room_id: 2,
     created_at: Sat, 07 Nov 2020 04:00:28 UTC +00:00,
     updated_at: Sat, 07 Nov 2020 04:00:28 UTC +00:00>
    
    
    처음엔 같은 결과로 보였는데 자세히 보면current_user_room[]의 배열이었다.→ 추기 current_user_room의 사용자는 where 방법을 통해 얻었다.
    배열용 방법을 검사해도 찾을 수 없다.where 방법은 데이터 그룹을 추출하는 것이기 때문에 당연합니다.
    그나저나 pluck 방법으로 얻고 싶었지만user_id 결과는 마찬가지였다.

    해결책


    배열에서 주우면 해결할 수 있을 거예요.
    따라서Rails 가이드보면take방법을사용할 수 있을 것 같다.얻고 싶은 게 하나라는 걸 알고 있으니까.
    take 방법으로 기록을 꺼냅니다.추출할 기록을 지정하지 않았습니다.
    rooms_controller.rb
    # 元のコード
    current_user_room = @room.user_rooms.where.not(user_id: current_user.id)
    
    # 対応コード(末尾に.takeを追加)
    current_user_room = @room.user_rooms.where.not(user_id: current_user.id).take
    
    ※ 또는 끝에 배열을 추가한 첫 번째[0]도 취소할 수 있습니다.

    수정된 코드


    rooms_controller.rb
    class RoomsController < ApplicationController
      def show
        @room = Room.find(params[:id])
        current_user_room = @room.user_rooms.where.not(user_id: current_user.id).take #.takeを追加
        user_id = current_user_room.user_id
        @user = User.find(user_id)
    
        @messages = @room.messages.includes(:user)
        @message = Message.new
      end
    end
    

    추기

    where가 되돌아오는 것은 수조가 아니라 ActiveRecord::Relation의 실례이다.
    # (where) current_user_room のクラスを確認
    pry(main)> current_user_room.class
    => UserRoom::ActiveRecord_AssociationRelation
    
    # (find) user_room1 の方も確認 
    pry(main)> user_room.class
    => UserRoom(id: integer, user_id: integer, room_id: integer, created_at: datetime, updated_at: datetime)
    
    이해가 아직 얕기 때문에ActiveRecordActiveRecord::Relation잘 조사하고 싶어요.

    끝말


    당분간 지금 대응할 수 있는 대책을 세웠는데 근본적으로 재검토하면 이 기술이 필요없을지도 모른다.눈치채면 고치고 싶어요.
    하지만 이번에where 행동에 닿아 많은 것을 배웠다.
    수준을 높이고 싶습니다. 만약 완비되지 않거나 다른 방법이 있다면 지적해 주십시오.

    참고 자료


    Rails 가이드
    ActiveRecord의find와where의 차이점→추기 시 참고

    좋은 웹페이지 즐겨찾기