There's an echo in my head

日々のメモ。

素のオブジェクトをfields_forに使う

例えばモデル的にGraph has_many Entityだけど、GraphはActiveRecordを使う一方でEntityには素のオブジェクトを使いたい場合。データストアが異なるとか。

class Graph < ActiveRecord::Base
  after_save :save_entities

  def entities
    @entities ||= [] # TODO: entitiesを読み込む
  end

  def entities_attributes=(attributes)
    # attributes = { "0" => { "name" => "foo", "body" => "bar" }, ... }
    @entities = attributes.map do |i, (attrs)|
      Entity.new(attrs)
    end
  end

  private

    def save_entities
      # TODO: entitiesを保存する処理
    end
end

class Entity
  include ActiveModel::Model

  attr_accessor :name, :body
end

class GraphsController < ActionController::Base
  def new
    @graph = Graph.new
    # 初回表示用にEntityをいくつか初期化
    @graph.entities << Entity.new
    @graph.entities << Entity.new
  end

  def create
    @graph = Graph.new(graph_params)
    @graph.save!
  end

  private

    def graph_params
      params.require(:graph).permit(
        :title,
        entities_attributes: [:name, :body]
      )
    end
end
# new.html.slim
= form_for @graph do |f|
  = f.text_field :title

  = f.fields_for :entities do |g|
    = g.text_field :name
    = g.text_area :body

  = f.submit

キモはentities_attributes=が定義してあること。これがあるかどうかでfields_forの挙動が変わる。

こんな雰囲気。端書きなので間違ってるかも。

このブログに出てくるコードスニペッツは、引用あるいは断りがない限りMITライセンスです。