I am just wondering whether this is a good approach to make a model request inside a cell definition....?
I am also need to define in general what is more convenient way to implement different representations for search results in different context from OOP point of view.
What do I need this for?
I have categories with items. I want to implement search results as a cell. Search results should be represented in a bit different way according to three cases:
E.g. let category be "animals" (this category contains: dog, cat, and bird items in the database) then I should see in browser:
Category Items dog cat bird
E.g let pattern be "do":
Similar Items Animals dog Cars dodge
E.g. let pattern be "do" and category be "animals":
Category Items dog Similar Items Cars dodge
I decided to experiment with cells gem to implement this stuff...
This is what i want to display via cell: (app/cells/search_result/display.html.haml)
%h1
= @category_items[:title]
%ul
- for i in @category_items[:items]
%li
= link_to "#{i.code} #{i.summary}", category_item_path(i.category.name, i.code)
%h1
= @similar_items_by_category[:title]
%ul
- for cat in @similar_items_by_category[:items_by_category].keys
%li
= "#{cat.name}"
%ul
- for i in @similar_items_by_category[:items_by_category][cat]
%li
= link_to "#{i.code} #{i.summary}", category_item_path(i.category.name, i.code)
This is my cell: (app/cells/search_result_cell.rb)
class SearchResultCell < Cell::Rails
def display options
setup! options
render
end
def setup! options
#some code here that defines
# category_items_title, like "Category Items"
# array_of_found_items
# similar_item_title, like "Similar Items"
# hash_of_found_items_by_category
#this code will be different for each search case in correspondent overridden function
@category_items = { title: category_items_title, items: array_of_found_items }
@similar_items_by_category = { title: similar_item_title, items_by_category: hash_of_found_items_by_category }
end
end
I am going to have separate cell class for each "search" case, derive it from the SearchResultCell (maybe I'll rename it to something like GenericSearchResultCell), and override setup! function for each case... And then will use builder to define wich class to build...
This is my view: (app/views/items/index.html.haml)
= render_cell :search_result, :display #, ... - and here some options...
Now QUESTIONS:
Should I make real search requests inside "setup!" function in a cell? And then make my controller ItemsController just "parse" route, and provide that options to be passed to my SearchCell...
Or should I make my ItemsController be responsible for both "parsing" route and making search requests (defining array_of_found_items, and hash_of_found_items_by_category by itself)? And then just pass all this stuff to the SearchCell as options...
Is all this "cells experiments" worthy? Is there any more convenient way to implement my "search" views and controllers?
You should decouple your querying logic completely from the controller and the rendering. Introduce a class ItemsFinder
that does all the search stuff and that returns a result set.
Now that you have proper model sets to talk about you can move on to the rendering. Usually, when the view is not too complex (no if-else, not too many nested partials) the "old" Rails partials way is just fine.
However, often you want to override just a small piece of a sub-sub-subpartial and that is where cells' view inheritance kicks in. It also encourages you to define interfaces for your "partials", so keep that in mind.
I agree with Max that cells usually helps keeping your controllers clean when you have reusable "widgets" in your view. Do not overuse it, thou ;-)