# controllers/books_controller.rb def new @book = Book.new end def create @book = Book.find(params[:id]) @book.save end
我没有使用新的和编辑html,而是使用coffeescript:
# views/new.js.coffee CustomModal.open "<%= j render('books/modal_form',book: @book) %>"
–
# views/create.js.coffee <% if @book.valid? %> CustomModal.hide() # Other callback scripts for showing alert,etc <% else %> # Script for showing errors in the modal <% end %>
以及触发模态的链接:
= link_to "Create Book",new_book_path,remote: true
现在,我面临的问题是这个链接只是在书的列表页面上使用.因此,在创建图书时,js回调会触发警报并使用更改更新列表.
现在我必须在另一个页面中添加此按钮,其中没有列表,所以我需要一个不同的回调(无论哪个回调都没关系).
所以,我必须添加到create.js.coffee之类的东西:
# views/create.js.coffee <% if @book.valid? %> CustomModal.hide() # if the list exists # show alert # update lists # else # do different things # end <% else %> # Script for showing errors in the modal <% end %>
这看起来很脏,但并不是那么糟糕.问题是我现在有超过3个条件,因为沿着webapp多次使用“Create Book”按钮.
那么,关于设计模式的任何想法呢?
解决方法
>促进瘦身控制者
>推广更小,更简洁的代码
>推动得墨忒耳法则
>使单元测试更容易
这是Presenter模式的一个非常好的描述:
https://gist.github.com/somebox/5a7ebf56e3236372eec4
要么:
http://eewang.github.io/blog/2013/09/26/presenting-the-rails-presenter-pattern/
基本上,它的工作方式是将业务逻辑移动到一个称为“演示者”的单独类中.此类包含您通常保留在控制器中的逻辑.
助手也有很好的记录,工作方式大致相同,但对于观点而言.助手比视图中的逻辑更容易测试.欲获得更多信息:
http://api.rubyonrails.org/classes/ActionController/Helpers.html
它可能看起来像这样(请注意,这只是未经测试的’伪’代码,我用它来说明模式):
# app/controllers/books_controller.rb helper BooksHelper def create book = Book.find(params[:id]) book.save @presenter = BookPresenter(book) end # app/presenters/book_presenter.rb # move your 'fat' controller logic here class BookPresenter attr_reader :book,:page_type def initialize(book,options={}) @book = book end private def page_type # custom code here for determining page type end ... end # app/helpers/books_helper.rb # move your view logic here module BooksHelper def custom_modal(book_presenter) if book_presenter.book.is_valid handle_valid_book(book_presenter) else # handle invalid book end end def handle_valid_book(book_presenter) custom_list_modal if book_presenter.page_type == 'has_list' custom_listless_modal if book_presenter.page_type == 'listless' # other conditions end def custom_list_modal # modularized JavaScript for pages with a list end def custom_listless_modal # modularized JavaScript for pages without a list end ... end
因此,在这种情况下,可以使用RSpec或您正在使用的任何测试框架在您的应用程序中轻松地对业务逻辑进行单元测试. JavaScript复杂性降低,测试变得更简单.如果您愿意,可以在不同的部分中单独定义JS输出,或者只是从辅助模块返回实际的JS.这是一个复杂的模式,最初采用,但随着时间的推移,一切都可能会感觉更自然,模块化,易于维护.