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

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

ただいまの
回答率

88.60%

関連テーブルの値の取得

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 636

takeke

score 59

RspecでJsonを返したいのですが、NoMethodError:
undefined method `status' for #<ActiveRecord::Associations::CollectionProxy []>がでてきてしまいます。

class Entry < ApplicationRecord
  belongs_to :user, class_name: :User, foreign_key: :user_id
  belongs_to :offer, class_name: :Offer, foreign_key: :offer_id
  belongs_to :recruit, class_name: :Recruit, foreign_key: :recruit_id

  scope :active, -> { where(is_deleted: 0) }

  class << self
    def users_entry(user_id)
      where(user_id: user_id)
    end
  end

  def pre_status
    self.status.to_sym
  end

  def pre_result
    self.result.to_sym
  end
end
class User::OffersController < ApplicationController
  before_action :set_user_user

  def show
    is_login = @login_user ? true : false
    offer = Offer.find(params[:id])
    recruits = offer.recruits.active
    # @entry = recruits.entries
    render json: {
        work: offer_as_json(offer, is_login),
        recruits: recruits_as_json(recruits, is_login),
        errors: []
    }
  end

  def create_entry
    entry = Entry.new({
      user_id: @login_user.id,
      offer_id: params[:id],
      recruit_id: params[:recruit_id]
    })

    if entry.save!
      render json: { success: true }
    else
      render json: { success: false, messages: entry.errors.full_messages }
    end
  end

  private
    def set_user_user
      if params[:token].present?
        @login_user = UserToken.find_by(token: params[:token]).user
      else
        @login_user = nil
      end
    end

    def recruits_as_json recruits, is_login
      recruits.map{|recruit|
        recruit_as_json recruit, is_login
      }.as_json
    end

    def recruit_as_json recruit, is_login
      entry = is_login ? recruit.entries.users_entry(@login_user.id) : nil
      {
        id: recruit.id,
        title: recruit.title,
        e_st: entry.present? ? entry.pluck(:status).first : "test",
        r_st: entry.present? && entry.pluck(:result) ? entry.pluck(:result).first : "pending",
      }
    end
end

spec

require 'rails_helper'

RSpec.describe "User::Offer", type: :request do
  describe "GET /user_offer" do
    let!(:user) {create(:user)}
    let!(:offer) { create(:offer_b) }
    let!(:recruits) do
      FactoryBot.create_list(:recruit, 3)
    end
    let!(:entry) {create(:entry)}
    let(:res) { JSON.parse(response.body).deep_symbolize_keys }
    context "正常系" do
      it "詳細が有効" do
        get '/api/user/offers/2'
        pp JSON.parse(response.body)
        expect(res).to eq(
          {
            :work => {
              id: offer.id,
              offer_name: "offer_name"
            },
            :recruits =>[
              {
                id: 1,
                title: "title",
                entry_status: "pending",
                result_status: "pending"
              },
              {
                id: 2,
                title: "title",
                e_st: "pending",
                r_st: "pending"
              }
            ],
            errors: []
          }
        )
      end
    end
  end
end


こちらのdef recruit_as_json recruit, is_loginの中のe_st: recruit.entries.status,の書き方が悪いのだと思うのですが、どう直したらいいのかわからず困っています。
少しでもアドバイスなどいただければ助かります。

他の必要なデータありそうでしたら言ってください。

以上よろしくお願いいたします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

+1

エラーメッセージにも現れているように、recruit.entriesコレクションですので、モデル1個に対して定義されているstatusも、コレクションに対しては取れません。

どのような値を取りたいのか(特に、今回の場合、entriesは空っぽのようです)を、まず定義してください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/03 15:27

    回答ありがとうございます!
    def recruit_as_json recruit, is_loginのところの最初に、entry = is_login ? recruit.entries.users_entry(@login_user.id) : nil
    と定義してあるのがそのまま使えると思うのですが、e_st: recruit.entries.statusをe_st: entry.statusとしましたところ、undefined method `status' for nil:NilClassとなりました。
    これは先ほど定義していたentry=のところが:nilとなっていたのでそうなっていると思うのですが、こちらの修正がわかりませんでした。

    キャンセル

  • 2018/12/03 15:48

    entryがnilの場合、何を返したいですか?

    キャンセル

  • 2018/12/03 17:19

    何を返すべきかわかりません。entryは必須ではないのでnilでいいのかもしれません。ただ、現在はentryが複数ある場合のspecをやっているつもりなのですが、entryが生成されてないのかもしれません

    キャンセル

  • 2018/12/03 17:51

    記事修正いたしました。こちらでspecが通りはしませんが、nilのエラーはなくなりました。
    statusやresultの結果が全てcontrollerのdef recruit_as_json recruit, is_loginで書いた、elseの結果になってしまうので、userのログイン判定か、userがいないのかもしれません

    キャンセル

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

  • ただいまの回答率 88.60%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る