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

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

ただいまの
回答率

91.36%

  • Ruby

    5168questions

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

  • Ruby on Rails 5

    77questions

【Rails5】find_byのnil挙動について

解決済

回答 1

投稿 2017/11/30 11:59

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

ssk

score 255

前提・実現したいこと

has_onehas_manyの関係を持つユーザ情報を
CSVファイルのアップロードでDBに反映させたいです。

■リレーション

#user.rb
has_one :section, primary_key: "section_id", foreign_key: 'id'
has_one :position, primary_key: "position_id", foreign_key: 'id'
has_one :division, primary_key: "division_id", foreign_key: 'id'
has_one :department, primary_key: "department_id", foreign_key: 'id'
has_one :authority, primary_key: "authority_id", foreign_key: 'id'

has_many :user_offices
has_many :offices, through: :user_offices
//インポートするCSVファイルのサンプルです。
id,section_id,department_id,division_id,position_id,office_ids
1,飲食事業,東京部署,新宿支店,店長,新宿支店;渋谷支店

発生している問題・エラーメッセージ

has_oneの関係
idに変換するのでfind_byで検索しています。

table['section_id']     = Section.find_by(name: table['section_id']).id
table['department_id']  = Department.find_by(name: table['department_id']).id
table['division_id']    = Division.find_by(name: table['division_id']).id
table['position_id']    = Position.find_by(name: table['position_id']).id


しかし、該当するnameがない場合
find_byの結果がnilとなり、そこで止まってしまいます。

undefined method `id' for nil:NilClass


has_manyの関係
has_oneとあまり変わりませんが、配列を生成しています。
一応、動いてはいますが、他に良い方法がありましたら、助言をしていただきたいです。

if table['office_ids'].present?
    a = table['office_ids'].split(';')
    table['office_ids'] = []

    a.each do |b|
      table['office_ids'] << Office.find_by(name: b).id
    end
end

補足情報(言語/FW/ツール等のバージョンなど)

・Rails (5.1.2)
参考サイト

has_oneの情報量って少ないですね、、
何卒、よろしくお願いいたします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

Section なら Section の,name と id の対照表が欲しいわけですよね。
CSV の 1 行ごとに検索するのも無駄なので,

section_name_to_id = Section.pluck(:name, :id).to_h

というハッシュを作っておくといいのではないでしょうか。

投稿 2017/11/30 12:32

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/11/30 13:13

    scivola様

    引き続き、ありがとうございます。
    仰る通り、ハッシュを作成することで対応できました。

    find_byで取得できなかった場合、nilが入るので
    そのままnilが代入されると考えていました。

    find_byで該当レコードがない場合はnilを返しでエラーになり
    ハッシュで該当キーがない場合はnilを返しエラーにはならない

    という理解でよろしいでしょうか?

    キャンセル

  • 2017/11/30 15:04

    ```rb
    Section.find_by(name: table['section_id']).id
    ```

    の場合,当該レコードが存在しなければ `find_by` が `nil` を返し,`nil` の `id` を呼ぼうとして `NoMethodError` になります。

    一方,ハッシュのデフォルト値(つまり存在しないキーに対する値)は,とくに指定しなければ `nil` です。

    キャンセル

  • 2017/11/30 15:06

    ありがとうございます。


    >の場合,当該レコードが存在しなければ `find_by` が `nil` を返し,`nil` の `id` を呼ぼうとして >`NoMethodError` になります。

    理解することができました。
    ご説明いただき、ありがとうございます。

    キャンセル

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

ただいまの回答率

91.36%

関連した質問

  • 解決済

    Railsでtext_field_tagにdata-promptを含めたい

    Railsでtext_field_tagにdata-prompt-positionというのを追記したいのですがどうしたらいいでしょうか? こうしたい。 <input t

  • 解決済

    ハッシュにして出力したい

    下記humans.csvをrbファイルで読み取って、記載した実行結果を出したいです。その際、途中まで書いて下記記載しているrbファイルのコードを使って出したいのですがどのように続き

  • 解決済

    csvから数値を読み取って計算結果をcsvに出力する方法

    name,score1,socore2 A,40,69 B,19,18 C,20,12 D,70,41 E,77,78,77.5 このcsvファイルからscore1とscore2

  • 解決済

    csvへの出力

    実現したいこと 下記のような内容のcsvファイルを出力させたいと思っています。 "name","score1","socore2","average" "A","40","

  • 解決済

    Railsのモデル並び替えについて

    Rails 5 Ruby 2.3.1 を利用しています。 【やりたいこと】 User.allなどでDBから取得したモデルを下記のように並び替えたいです。 あるカ

  • 解決済

    Ruby on Rails 表示順の変更に関して

    前提・実現したいこと Rails4で作成。 表示順の変更に関して、 2chのスレッド一覧のように、表示順をスレッドにコメントがあったら上位に表示させるといった場合、どのよ

  • 解決済

    Ruby(Ruby on Rails)で特定の値を合計したい

    開発環境 MacOS X 10.11 El Capitan Ruby 2.3.1 Ruby on Rails 4.2.6 発生している問題・エラーメッセージ ECサ

  • 解決済

    rubyプログラミングの空白処理について

    英語文章を分析するためにRubyを使ってプログラムを書いています。 また、英語はTEDのサイトのスクプトを使用しています。 実際に、単語と単語を空白で区切り、配列に格納する

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

  • Ruby

    5168questions

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

  • Ruby on Rails 5

    77questions