[rails] accepts_nested_attributes_for の場合は、inverse_of を付けておくと良い気がする

# inverse_of
- [ActiveRecord4(Rails4)のリレーションをinverse_ofで最適化する方法 - Hive Color](http://hivecolor.com/id/150)
- [inverse_of を使うと何ができるのか - 野生のエンジニアがあらわれた(チラ裏)](http://d.hatena.ne.jp/shindo_r/20130227/1361930960)
- [ActiveRecord::Associations::ClassMethods](http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#label-Bi-directional+associations)

上記サイト様が上げているサンプルが分かりやすい

#### inverse_ofを使わなかった場合
```rb
 class Dungeon < ActiveRecord::Base
  has_many :traps
end

class Trap < ActiveRecord::Base
  belongs_to :dungeon
end


d = Dungeon.first
t = d.traps.first
d.level == t.dungeon.level # => true
d.level = 10
d.level == t.dungeon.level # => false

d.object_id ==  t.dungeon.object_id #=> false
```

#### inverse_ofを使った場合
```rb
class Dungeon < ActiveRecord::Base
  has_many :traps, :inverse_of => :dungeon
end

class Trap < ActiveRecord::Base
  belongs_to :dungeon, :inverse_of => :traps
end


d = Dungeon.first
t = d.traps.first
d.level == t.dungeon.level # => true
d.level = 10
d.level == t.dungeon.level # => true

d.object_id == t.dungeon.object_id #=> true
```

つまり inverse_of を使うと、dとt.dungeonがメモリ内で同一のインスタンスを見るようになる。

# with accepts_nested_attributes_for
accepts_nested_attributes_for の場合なぜ良いか。

親recordが出来る前に、associationをたどれるようになるのがよい。

## inverse_ofを付けない場合
```rb
# app/models/survey.rb
class Survey
    belongs_to :user
    has_many :questions
    accepts_nested_attributes_for :questions
end

# app/models/question.rb
class Question
    validates :survey_id, presence: true
    belongs_to :survey
end
```

こんなmodelをまとめてsaveすると

```rb
    def create
        @survey = current_user.surveys.build(survey_params)
        if @survey.save
            redirect_to @survey
        else
            render :new
        end
    end
```

子recordのvalidate時には、親recordができていないので、親をたどれない。
子recordのcreate時なら、親recordができているので、たどれるようになる。

#### 子recordのbefore_validate内
```rb
[1] pry(#<Question>)> self
=> #<Question id: nil, survey_id: nil, name: "hoge", created_at: nil, updated_at: nil>
[2] pry(#<Question>)> survey
=> nil
```
親をたどれない

#### 子recordのbefore_create内
```rb
[1] pry(#<Question>)> self
=> #<Question id: nil, survey_id: 1, name: "hoge", created_at: "2014-12-27 05:30:55", updated_at: "2014-12-27 05:30:55">
[2] pry(#<Question>)> survey
=> #<Survey id: 1, name: 'aaa', created_at: "2014-12-27 05:30:55", updated_at: "2014-12-27 05:30:55">
```
survey_idがあるので、before_createなら親をたどれる。

## inverse_ofを付けた場合
```rb
# app/models/survey.rb
class Survey
    belongs_to :user
    has_many :questions, inverse_of: :survey
    accepts_nested_attributes_for :questions
end

# app/models/question.rb
class Question
    validates :survey, presence: true
    belongs_to :survey, inverse_of: :questions
end
```

#### 子recordのbefore_validate内
```rb
[1] pry(#<Question>)> self
=> #<Question id: nil, survey_id: nil, name: "hoge", created_at: nil, updated_at: nil>
```
survey_idはnilだけど。。。

```rb
[2] pry(#<Question>)> survey
=> #<Survey id: nil, name: 'aaa', created_at: nil, updated_at: nil>
```
before_validate段階で、親がたどれる！
しかもこの際に、SQLは発行されないです。（idでたどる訳じゃないから、そりゃそうか）

※ 投稿用に自分の検証環境のclass名などをSurveyとQuestionに書き換えちゃったので、なんか誤植あったらすいません。

### inverse_ofがなくて困る事
何となく思うのは、外部制約キーを付けている場合。
あと、子の`before_validate`内にて、親recordとの複合条件にてvalidateをしたい場合などに困りそう。

自分の場合は、親 > 子1 > 子2 の様な多重はrelationで、子2から親1の中身を使ってvalidateしよう、と思った

### inverse_ofの制約
>throughアソシエーションと一緒には動きません
polymorphicアソシエーションと一緒には動きません
for belongs_to associations has_many inverse associations are ignored.

らしいです。

## 参考
- [Always use :inverse_of to connect two models in a belongs_to/has_many relationship - makandropedia](http://makandracards.com/makandra/12331-always-use-inverse_of-to-connect-two-models-in-a-belongs_to-has_many-relationship)
- [inverse_of を使うと何ができるのか - 野生のエンジニアがあらわれた(チラ裏)](http://d.hatena.ne.jp/shindo_r/20130227/1361930960)
- [Rails -- how to populate parent object id using nested attributes for child object and strong parameters? - Stack Overflow](http://stackoverflow.com/questions/16782990/rails-how-to-populate-parent-object-id-using-nested-attributes-for-child-obje)
- [kueda.net / Blog » Blog Archive » validates_presence_of and accepts_nested_attributes_for](http://kueda.net/blog/2012/09/04/validates_presence_of-and-accepts_nested_attributes_for/)
- [ActiveRecord::Associations::ClassMethods](http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#label-Bi-directional+associations)
- [ActiveRecord4(Rails4)のリレーションをinverse_ofで最適化する方法 - Hive Color](http://hivecolor.com/id/150)