0

This is probably very simple to do, but I am having trouble wrapping my head around it. I have a model called "document" and a field within the model called: category.

Category can consist of 3 options:

  • Meeting Notes
  • Sales
  • Engineering

In my view I have: [index.html.erb]

<% @documents.each do |document| %>
  <div class="table-div">
    <div class="col-sm-12 col-md-12 div-table-label">
      <strong><%= document.category %></strong>
    </div>
    <div class="col-sm-12 col-md-12">
      <%= link_to document.title, document %>
    </div>
  </div>
<% end %>

In my controller, just the default:

  def index
    @documents = Document.all
  end

What I want to do is loop through each category and grab all documents tied to that category to group them together.

Right now, it just prints each document with its category heading in the order it is created, no logic to it at all.

Thanks.

4 Answers 4

1

Try

def index
   @documents = Document.where(true).order(:category).order(:title)
end

so that the ordering is done on the database which can be faster especially if you have a index on the category column and to order the documents by title

And change the view to render the header when ever a new category is encountered

<% category = "" %>
<% @documents.each do |document| %>
  <div class="table-div">
    <% if category != document.category %>
    <div class="col-sm-12 col-md-12 div-table-label">
      <strong><%= document.category %></strong>
    </div>
    <% category = document.category %>
    <% end %>
    <div class="col-sm-12 col-md-12">
      <%= link_to document.title, document %>
    </div>
  </div>
<% end %>
Sign up to request clarification or add additional context in comments.

1 Comment

This seems to be what I need. Can I also order by created_at as well? Having trouble throwing that in there..
1

What I want to do is loop through each category and grab all documents tied to that category to group them together.

I'd start with an easy way to find documents by category name. For this, a scope is great:

class Document
  # ...
  scope :for_category, -> category_name { where(category: category_name) }
  # ...
end

Then you could loop through the category names and find all documents for that category, such as:

ALL_CATEGORIES = ["Meeting Notes", "Sales", "Engineering"]

All_CATEGORIES.each do |category|
  documents = Document.for_category(category)
  # Do something with the documents for this category...
end

Of course, it's not really ideal to put this much logic into the view, but expanding on this is a bit beyond the scope of this question. If curious, look into Avdi Grimm's Exhibit Pattern.

Comments

1

You could always create a static method in the Document class that does the following:

class Document
    ...
    def self.all_by_category
        docs_by_category = {}
        all.each do |document|
            if docs_by_category.has_key? document.category
                docs_by_category[document.category] << document
            else
                docs_by_category[document.category] = [document]
            end
        end

        docs_by_category
    end

You could then look through the returned hash and print out the documents that are a part of each category like so:

def index
    #you may want to change the name because it's misleading to leave it as @documents
    @documents_by_category = Document.all_by_cateogry # returns hash
end

and then

<% @documents_by_category.each do |category_name, documents|
       documents.each do |document| %>
           YOUR CODE HERE 
       <% end %>
<% end %>

If the number of documents are high, however, this method may become inefficient.

It might be better to create another database table for categories, and then use a Category model to query each category and get their associated documents.

Comments

0

do you mean something like:

@categories.each do |cat|
  #  output cat.name or something
  cat.documents.each do |doc|
    # doc.name or whatever
  end
end

you'd obviously need to get the @categories in your controller

def index
  @categories = Category.all
end

alternatively you could be getting the documents grouped by their category

def index
  @documents = Document.all.group_by(&:category)
end

see here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.