fields_forでhas_manyなフィールドを作って、それをどんどんページ内で追加して行きたい場合ありますよね。そんな時はモデルに、
accepts_nested_attributes_for
http://apidock.com/rails/ActiveRecord/NestedAttributes/ClassMethods/accepts_nested_attributes_for
を指定してgemで
nested_form
https://github.com/ryanb/nested_form
を使うと簡単にできます。できるはずなんですが、自分の環境でform-builderをもろもろ拡張している関係か、link_to_addがどうもちゃんと動かなかったのでjQueryでさっくり最後のフィールドをコピーして末尾に追加する仕組みを作りました。
$.fn.nestedResource = function(options) {
var result = {
update: function(fields) {
$(fields).find("input").each(function(index, field) {
$(field).attr("id", $(field).attr("id").replace(/\_[0-9]+\_/,"_" + count + "_"));
$(field).attr("name", $(field).attr("name").replace(/\[[0-9]+\]/,"[" + count + "]"));
});
},
append: function() {
this.update(templateDom);
count++;
$(tailSelector).before($(templateDom).clone(false));
},
};
var count = 0;
var selector = options["selector"];
var tailSelector = options["tail-selector"];
$(selector).each(function(index, fields) {
result.update(fields);
count++;
});
var templateDom = $(selector).last().clone(false);
return result;
};
.clone(false)とfalseを指定しないと、イベントも一緒にコピーされてしまいます。
tail-selectorで指定した箇所にコピーしたDOMを入れます。
var nestedResource = $(document).nestedResource({
"selector": "#schedules .fields",
"tail-selector": "#schedules_tail"
});
フィールドの追加はこんな感じで呼び出します。
<%= link_to "フィールドを追加", "javascript:void(0)", :onclick=> "nestedResource.append(); return false;" %>
これで分かりやすくフィールドがコピーされて増えます。