困ったときのメモ ver.2.0

主に Ruby on Rails のメモ。など。

醜悪な設計とコードを書いてみるー(多対多でなく多対配列)

はじめに

このところチカラワザに凝ってて、スマートでないことを知りつつも、なんとかしてみようというチャレンジの記録。できないとは言いたくなかっただけ。

多対多の関連におけるチェックボックスでの紐付けは簡単にできた(http://d.hatena.ne.jp/ikad/20110604/1307158317)ので、今回はこれをいじってみた。
テーマは多対多の片方をモデルでなくただの配列でやったらどうなるか・・・。

普通なら...

今回は...

なんでこんなことをしたかというと、
 ・リストの数が少なく、変更もないためメンテしない(もしくは変更するならそれなりの覚悟)
 ・正規化によるテーブルの増加がやだ
 ・includeもjoinめんどい
なんて、後ろ向きで拡張性もへったくれもない理由でもなんとかしてみたかった。

背景と登場人物

ブログのタグ付けを想定。

モデル
 Post ・・・ ブログ記事
 Tag ・・・・ ブログ記事につけられたタグ

配列
 tag_list ・・・ タグのリスト

準備作業

とりあえずscaffoldとmodelをば。

rails g scaffold Post title:string body:text
rails g model Tag name:string post:references

app/helpers/application_helper.rbに配列をば。

  def tag_list
    %w(dog cat bird fish)
  end

コード書いてみるー

app/modeld/post.rbが主戦場なのでまるごと

class Post < ActiveRecord::Base
  has_many :tags, :dependent => :destroy
  
  attr_accessor :tag_names  #フォームからpostされる
  after_save :tags_update
  
  #いろいろ捗る
  def mytag_names
    arr = []
    self.tags.all.map {|tag| arr << tag.name}
    return arr
  end
  
  def tags_update
    self.tags.destroy_all
    
    tag_names.each do |name|
      self.tags.create(:name => name)
    end if tag_names
  end
end

app/views/posts/_form.html.erbにはチェックボックスのリストを追加

  <div>
    <% tag_list.each_with_index do |name, idx| %>
      <%= check_box_tag 'post[tag_names][]', name, @post.mytag_names.include?(name), :id => "tag_#{idx}" %>
      <%= label_tag "tag_#{idx}", name %><br>
    <% end %>
  </div>

app/views/psots/index.html.erbにはタグのリストを追加

    <td><%= post.mytag_names.map {|name| name + ","} %></td>

おわりー

やってみたらいろいろ嵌ったー。チェックボックスのつかいどころ間違えると痛い目見ることがよくわかりました。
素直に多対多のモデルでやりましょー。

できあがってみても、焦燥感しか得られない。。