18232


[【Rails】fields_for と accepts_nested_attributes_for - kzy52's
blog](http://kzy52.com/entry/2013/07/10/200144)

**引用：**

> accepts_nested_attributes_forです。すごく便利。  
>  profile_attributes= と academics_attributes= メソッドが追加される
>
> **登録時**  
>  params = { user: { name: 'Test', profile_attributes: { nickname: 'test' } }
> }  
>  user = User.create(params[:user])  
>  user.profile.id # => 1  
>  ser.profile.nickname # => 'test'
>
> **更新時**  
>  params = { user: { profile_attributes: { id: '1', nickname: 'test2' } } }  
>  user = User.find 1  
>  user.update params[:user]  
>  user.profile.nickname # => 'test2'

  
  
**入れ子のForm** で使う`accepts_nested_attributes_for`ですが、  
**末尾が=のメソッド** ができることがわかりました。

また **末尾が=のメソッド** の意味は、  
[ruby on rails - Rubyのメソッド名の末尾に = (イコール) -
スタック・オーバーフロー](https://ja.stackoverflow.com/questions/18114/ruby%e3%81%ae%e3%83%a1%e3%82%bd%e3%83%83%e3%83%89%e5%90%8d%e3%81%ae%e6%9c%ab%e5%b0%be%e3%81%ab-%e3%82%a4%e3%82%b3%e3%83%bc%e3%83%ab)  
に質問させていただきわかりました。

さて、上記引用の`create`と`update`ですが、 **Hash**
を与えているだけにすぎず、`accepts_nested_attributes_for`で生えた **末尾が=のメソッド**
と関係性が頭の中でひも付きません。 **Hash** を与えているだけに過ぎないのに **新しくメソッドを生やす意味** とはなんでしょうか？
またこのようなテクニックが簡単にわかる簡単なサンプルソースを付けていただけるとうれしいです。


CC BY-SA 3.0
2015-10-28T15:08:18.027
18179
2015-10-30T04:17:39.957
2017-04-13T12:52:38.920
-1
9008
question
ruby-on-rails ruby
accepts_nested_attributes_forで生えたメソッドとcreateやupdateの関係性


## RoRでの似たような該当部分

`accepts_nested_attributes_for`とは若干ずれますが、  
`*=`を使ったテクニックとしては下記が該当するでしょうか。  
（ActiveModel::Modelの話なのでそう大きくはずれていない）

[Method: ActiveModel::Model#initialize — Documentation for rails
(4.0.0)](http://www.rubydoc.info/docs/rails/4.0.0/ActiveModel%2FModel%3Ainitialize)

**File 'activemodel/lib/active_model/model.rb', line 78**

[code]

    def initialize(params={})
      params.each do |attr, value|
        self.public_send("#{attr}=", value)
      end if params
    
      super()
    end
    
[/code]

  

## Hashでインスタンス変数をSETする例（自作する場合）

[code]

    class Hoge
      attr_accessor :a, :b
    
      def initialize(params={})
        params.each do |attr, value|
          self.public_send("#{attr}=", value)
        end if params
      end
    end
    
    hoge = Hoge.new(a: "A", b:"B")
    puts hoge.a
    puts hoge.b
    
[/code]

### *=メソッドはないけどよいの？

`attr_accessor`のソースを読みに行くと、

[code]

    # attr_accessor(symbol, ...)    -> nil
    # attr_accessor(string, ...)    -> nil
    #  
    # Defines a named attribute for this module, where the name is
    # <i>symbol.</i><code>id2name</code>, creating an instance variable
    # (<code>@name</code>) and a corresponding access method to read it.
    # Also creates a method called <code>name=</code> to set the attribute.
    # String arguments are converted to symbols.
    # 
    #    module Mod
    #      attr_accessor(:one, :two)
    #    end
    #    Mod.instance_methods.sort   #=> [:one, :one=, :two, :two=]
    def attr_accessor(*several_variants)
        #This is a stub, used for indexing
    end
    
[/code]

となっており

**`Mod.instance_methods.sort #=> [:one, :one=, :two, :two=]`**  
の部分から、  
`attr_accessor`が **末尾=メソッド** を生やしているから不要でしょう。


CC BY-SA 3.0
2015-10-30T03:03:28.217
18232
2015-10-30T04:17:39.957
2015-10-30T04:17:39.957
9008
9008
18179
answer

[code]

    user = User.create({:name => 'hoge', :email => 'fuga'})
    
[/code]

は

[code]

    user = User.new
    user.name = 'hoge'
    user.email = 'fuga'
    user.save
    
[/code]

などとも書けますが、Nested Attributesを使う時は後者の形式は使えない、では困るでしょう。


CC BY-SA 3.0
2015-10-30T03:07:13.350
18233
2015-10-30T03:07:13.350
5793
18179
answer