2008年11月11日 星期二

Complex Forms

http://railscasts.com/episodes/73
http://railscasts.com/episodes/74
http://railscasts.com/episodes/75
http://api.rubyonrails.org/classes/ActionView/Helpers/PrototypeHelper/JavaScriptGenerator/GeneratorMethods.html#M001254
http://api.rubyonrails.org/classes/ActionView/Helpers/JavaScriptHelper.html#M001341

[View edit.rhtml]
<div id='books'>
<%= render :partial => 'book', :collection => @user.books %>
</div>
<%= add_book_link 'add book'%>


[user helper]
module UsersHelper
def add_book_link(name)
link_to_function name do |page|
page.insert_html :bottom, :books, :partial => 'book', :object => Book.new
end
end
end

[View book partial]

<% fields_for "user[books][]", book do |b| %>
<%= b.text_field :name %>
<%= link_to_function 'remove', "this.up('.book').remove()"%>
<% end %>




下面是強化版

[view, edit.rhtml]
<div class='book'>
<% fields_for "user[books][]", book, :index => nil do |b| %>
<%= b.text_field :name %>
<% if book.new_record?%>
<%= link_to_function 'remove', "this.up('.book').remove()" %><br /> <= 單純移掉 html, 反正是new出來的還沒存
<% else %>
<%= link_to_function 'remove', 'mark_for_destory(this)' %>
<%= b.hidden_field :id %> <= 原有的 object 把 id藏起來
<%= b.hidden_field :should_destroy, :class => 'should_destroy' %> <= 用來記真的要砍的記號
<% end %>
<% end %>
</div>


[js application.js]
function mark_for_destory(element) {
$(element).next('.should_destroy').value = 1; <= 做了記號後
$(element).up('.book').hide(); <= 藏起來
}

[Controller, user_controller.rb]
@user.update_attributes(params[:user])

[Model book.rb]
attr_accessor :should_destroy

def should_destroy?
should_destroy.to_i == 1
end

[Model user.rb]
after_update :save_books

def books=(books_attrs)
books_attrs.each do |attrs|
if attrs[:id].blank? <= 如果id是空的就是需要new的
books.build(attrs)
else
book = books.detect{|b| b.id == attrs[:id].to_i}
book.attributes = attrs <= 這時上面那些有被destroy 的 should_destroy 也會被給值
end
end
end

def save_books <= parent object update_attribute would not update the children attribute, so we need to save by ourself
books.each do |book|
if book.should_destroy?
book.destroy
else
book.save # if Calling save(false) saves the model without running validations.
end
end
end



沒有留言: