18580
多くのlibrary（製品）があり、それぞれのlibraryには多くのdoc（書類が）あります。またそれぞれの製品に多くのpict(画像）がある。  
二つに分けたいのは書類は種類や備考がありますが、pictはサムネールの表示をしたいからです。

library.rb

```

    has_many :docs
    has_many :picts
    
```

doc.rb

```

    belongs_to :library
    
```

pict.rb

```

    belongs_to :library
    
```

としてあります。ここでlibraryコントローラーで

```

    def show
      @docs = @library.docs.where(params[:library_id])
    end
    
    def pictshow　#ルーティングの設定はしてある
      @picts = @library.picts.where(params[:library_id])
    end
    
```

になっておりますが、showではエラーが出ないのですが、pictshowで

```

    NoMethodError in LibrariesController#pictshow
    undefined method `picts' for nil:NilClass
    
```

になってしまいます。原因が解りません
CC BY-SA 3.0
2015-11-09T11:47:11.610
18576
2015-11-22T04:16:34.000
2015-11-09T23:56:02.813
85
13186
question
ruby-on-rails
Railsで複数のhas_manyを持ったモデルを作りたい
`@picts = @library.picts`
の時点で値が`nil`になっています。該当の`@library`が一枚も`pict`を持っていないためです。
CC BY-SA 3.0
2015-11-09T12:19:22.150
18578
2015-11-09T12:19:22.150
3271
18576
answer
>
```

>     NoMethodError in LibrariesController#pictshow
>     undefined method `picts' for nil:NilClass
>  
```

`@library`が`nil`なので`@library.picts`が`NoMethodErrorになっています。

scaffoldで生成したコントローラであればコードはこうなっていると思います。

```

    class LibrariesController < ApplicationController
      before_action :set_library, only: [:show, :edit, :update, :destroy]
    
      def show
      end
    
      private
        # Use callbacks to share common setup or constraints between actions.
        def set_library
          @library = Library.find(params[:id])
        end
    end
    
```

`set_library`メソッドによって`@library`に然るべきidのLibraryがロードされるのですが、`set_library`が呼び出されるのは

```

      before_action :set_library, only: [:show, :edit, :update, :destroy]
    
```

と、ここで指定されたメソッド(アクション)のみです。自分で追加したメソッドであれば、`before_action`にもそれを追加しないと`@library`は設定されないまま(参照したら`nil`)になります。

ついでに指摘しておきます

```

    @docs = @library.docs.where(params[:library_id])
    
```

というコードですが、`@library.docs`は

```

    @docs = Doc.where(library_id: @library.id)
    
```

と同じです。多分やりたいことは

```

     @docs = @library.docs
    
```

で十分なんじゃないでしょうか。

さらに言うと、`where(params[:library_id])`は多分`where(10)`とかになるので、意図しないクエリになっていると思います。

(暗黙の型変換でSQLとしては`SELECT ... WHERE TRUE`になってるかな？)
CC BY-SA 3.0
2015-11-09T13:31:16.153
18580
2015-11-09T13:31:16.153
5793
18576
answer
```

    @library = nil 
    @library.picts 
    #-> undefined method `picts' for nil:NilClass
    
```

になります。  
もし、nilの場合にエラーを出したくないならば、

```

     @library = nil 
     @library.try(:picts)
     #-> nil(エラーは出ない)
    
```

を使うことで避ける事ができます。
CC BY-SA 3.0
2015-11-22T04:16:34.000
19156
2015-11-22T04:16:34.000
12758
18576
answer