Domains - aggregating all updates that have a given domain
Now we've reached a point where we'd like to offer a quick overview of all the content in a given domain. Since our Updates have a Domain field, we will start by displaying the recent updates that share the same domain.
How should we proceed?
Let's go back to the Rails diagram:
Link and routes
To see all content related to a domain, we'd like our users to go to a page like casemanagementsystem.md/domains/social
or localhost:3000/domains/education
.
Generally, all content from a given domain will be located at localhost:3000/domains/domain_type
. These pages will be accessible to authenticated users.
Under this premise, open the file config/routes.rb
and edit the block:
authenticated :user do
root to: "cases#index", as: :authenticated_root
end
to include:
authenticated :user do
root to: "cases#index", as: :authenticated_root
get "domains/:domain_type" => "domains#filter", as: :domain_filter
end
In the line above, domains/:domain_type
is able to resolve all links of the form domains/anytextgoeshere
with the aid of the action filter
in the domains
controller. anytextgoeshere
will be passed as the domain_type
parameter to the filter
action. The path associated with this series of links is thus called domain_filter_path
.
Controller and action
Save the file, open the browser and try to visit a page, let's say localhost:3000/domains/social
.
You will get the following error:
The error states that there is no DomainsController. Let's create one.
Create a new file, app/controllers/domains_controller.rb
type in the following, then save the file:
class DomainsController < ApplicationController
end
Refresh the browser:
A new error! There is no filter
action in the DomainsController
. We need to add one.
We would like the filter
action to return all the updates for which the domain
is the same as the domain_type
the filter action receives as a parameter. We will write this programmatically like this:
class DomainsController < ApplicationController
def filter
@updates = Update.where({:domain => params[:domain_type]})
end
end
View
Save the file, refresh.
A new error, this time - missing template. We know we need to create a view.
Create the app/views/domains
folder and the app/views/domains/filter.html.erb
file, write anything in it, save the file and refresh the page:
Phew! It works. We only have to make it work properly.
Rendering the updates
We now know that the filter action creates an instance variable @updates
that has all the updates form the domain_type
we passed as parameter.
In the previous chapter, we also carefully prepared a partial we can use when we want to render this collection.
What follows is both straightforward and magic. Edit the app/views/domains/filter.html.erb
file to include the following:
<div class="container">
<h3>Updates</h3>
<%= render :partial => "updates/update_with_case", :collection => @updates, as: :u %>
</div>
Save the file and refresh the browser page:
Oh wow! It worked!
Refinements
Edit the app/views/domains/filter.html.erb
to add the internal navbar and the domain name:
<%= render "shared/internal_navbar" %>
<div class="container">
<h2><%= params[:domain_type] %></h2>
<h3>Recent updates</h3>
<%= render :partial => "updates/update_with_case", :collection => @updates, as: :u %>
</div>
Since our service may be very-very good and popular, we'd like to show only the most recent, let's say 200 updates from a given domain. For this, in the DomainsController, change the filter
action to:
def filter
@updates = Update.where({:domain => params[:domain_type]}).order(id: :desc).limit(200)
end
Refresh the page:
Beautiful.
Linking to the domain page
Now that we have the domain page, let's make the labels on the updates act as links to the page. To do this, and thanks to the preparations in the previous chapter, we will have to edit only two partials.
Open the file app/views/updates/_update.html.erb
and change the following line:
<span class="label label-primary"><%= u.domain %></span>
to
<span class="label label-primary"><%= link_to(u.domain, domain_filter_path(u.domain), style: "color: white") %></span>
Open the file app/views/updates/_update_with_case.html.erb
and change the line:
<span class="label label-primary"><%= u.domain %></span>
to
<span class="label label-primary"><%= link_to(u.domain, domain_filter_path(u.domain), style: "color: white") %></span>
You have already recognized the use of the link_to
helper and the inline style for white color of the text.
Restricting the domain selection
Right now, the users can post updates from virtually any domain. Since the applications have restricted use, we would like them to be able to select, not type, one of the pre-defined domains.
The component that helps us achive this is a select - you can find a sample in the Rails Boostrap Forms gem documentation.
Open the app/views/cases/show.html.erb
file, locate the code that renders the Post a new update
form.
Next, we will have to replace the line:
<%= form.text_field :domain, label: "Domain", required: true %>
with the following:
<% possible_domains = [["Social", "social"], ["Financial", "financial"], ["Education", "education"]] %>
<%= form.select :domain, possible_domains, label: "Domain", required: true %>
What we did is create a variable, possible_domains
, that contains a list of domains and the labels used to display them. Next, we are using a select helper that will show the user the possible_domains
she can choose from when she creates an update.
This is how it looks like in use: