こんにちは。
ウェブディレクターの鈴木です。

今日は新しいwebアプリの開発をしていました。
その際にattributesの取得で大ハマりして予定をだいぶ超過してしまったので、シェアしておきたいと思います。

今回のwebアプリはTwitterで見かけたアプロが面白そうだったので、真似て作ってみようと思ったのがきっかけです。なので、仕様など含めて見た目と動作から勝手に作っています。

そして、今回のwebアプリは自分が作る中では初めてmodelがありません。そのため利用する項目をclassの中で、attr_accessor で定義しているのですが、controllerからattr_accessorの一覧を取得する方法に苦戦しました。

参考にしたプログラムはmodelが存在したので、model.attributesでさらっと取得していたんですけど、attr_accessorだとそれができません。結果としてはclassに「attributes」と「attributes=」を実装しました。コードは以下の通りです。

def attributes
  {a: @a, b: @b, c: @c}
end
def attributes=(args={})
  args.each do |key, value|
    self.send("#{key}=", value) if self.methods.include?(key.to_sym)
  end
end

attributesはinstance_variablesから取得する方法も考えたんですが、キーの部分が無理やりになるかなと思って一旦ベタがきにしてしまったんですが、今後増えたりすることを考えるとinstance_variablesでeachした方がいいかなと思ってます。ただ、instance_variablesで取得する一覧って「:@a」とかの形式になっていて@が邪魔なんで取り除く感じでいいのかな?また、attributes=はinitializeと全く同じ実装なのでDryじゃないです。。。

今回はattributesの結果をHashで取得したかったので、こんな感じになりました。あと、Wizard型のフォームを初めて作成してroutesの設計と合わせて手間取ってしまいました。

理由としてWizard型のフォームの入力をcontrollerを分けて実装したんですが、戻るボタンを考慮したらなんか複雑になってしまい、ネットで見ていたらsessionを使った方法が紹介されていたので、そちらを参考に実装しました。

ただ、今考えると1フォームでレイヤーの表示・非表示を切り替えるだけの方が簡単でよかったんじゃないかなと思い出しています。

なので、一旦controllerを分けた実装を行なって、その後にレイヤー切り替え版も作ってみようかなと考えています。

そして、attributesのもっといい解決方法などあればぜひ教えてください。

最後まで読んでいただき、ありがとうございました。