Question

I am new to Ruby and Sinatra but I've read a bit about Rails. One of the things Rails masters tell us to do is to leave code out of the templates.

Well, here is my code, right where the information is needed in my template. It works but, for the sake of learning the best practices, how could I move this out of my template into my app.rb file without repeating it in every block of code (CRUD) which relies on the template?

<h2>Status</h2>
<ul>
  <li>Received<span><%= Inbox.count %></span></li>
  <li>Sent<span><%= Outbox.all(:processed => 1).count %></span></li>
  <li><Scheduled<span><%= Outbox.all(:error => -1).count %></span></li>
  <li>Error<span><%= Outbox.all(:error.not => [-1,0]).count %></span></li>
</ul>

Thanks for the pointers.

Was it helpful?

Solution 2

As an alternative to @Beat Richartz's answer - not because it's wrong but because there are lots of alternatives…

1. Helpers

Helpers are available in templates. e.g.

helpers do
  def mailbox_stats
    @mailbox_stats ||= {
      :inbox_count     => Inbox.count
      :sent_count      => Outbox.all(:processed => 1).count
      :scheduled_count => Outbox.all(:error => -1).count
      :errored_count   => Outbox.all(:error.not => [-1,0])
    }
  end
end

and in the template:

<h2>Status</h2>
<ul>
  <li>Received<span><%= mailbox_stats[:inbox_count] %></span></li>
  <li>Sent<span><%= mailbox_stats[:sent_count]  %></span></li>
  <li><Scheduled<span><%= mailbox_stats[:scheduled_count] %></span></li>
  <li>Error<span><%= mailbox_stats[:errored_count] %></span></li>
</ul>

2. Settings

Settings probably aren't the best idea for this situation, but it can be done, maybe if you wanted to set some defaults:

config do
  set :mailbox_stats, {
      :inbox_count     => 0
      :sent_count      => 0
      :scheduled_count => 0
      :errored_count   => 0
    }
end

before do
  if @user.has? :inbox # or something relevant
    settings.mailbox_stats.replace( {
      :inbox_count     => Inbox.count
      :sent_count      => Outbox.all(:processed => 1).count
      :scheduled_count => Outbox.all(:error => -1).count
      :errored_count   => Outbox.all(:error.not => [-1,0])
    })
 end
end

<h2>Status</h2>
<ul>
  <li>Received<span><%= settings.mailbox_stats[:inbox_count] %></span></li>
  <li>Sent<span><%= settings.mailbox_stats[:sent_count]  %></span></li>
  <li><Scheduled<span><%= settings.mailbox_stats[:scheduled_count] %></span></li>
  <li>Error<span><%= settings.mailbox_stats[:errored_count] %></span></li>
</ul>

3. Local variables

Like limiting your scope?

get('/or_so') do
  erb :your_template, :locals => { :mailbox_stats => {
          :inbox_count     => Inbox.count
          :sent_count      => Outbox.all(:processed => 1).count
          :scheduled_count => Outbox.all(:error => -1).count
          :errored_count   => Outbox.all(:error.not => [-1,0])
    }
  }
end

in the template:

<h2>Status</h2>
<ul>
  <li>Received<span><%= mailbox_stats[:inbox_count] %></span></li>
  <li>Sent<span><%= mailbox_stats[:sent_count]  %></span></li>
  <li><Scheduled<span><%= mailbox_stats[:scheduled_count] %></span></li>
  <li>Error<span><%= mailbox_stats[:errored_count] %></span></li>
</ul>

I'd probably use a helper.

OTHER TIPS

Just load the counts into instance variables where you define the routes:

get('/or_so') do
  @inbox_count     = Inbox.count
  @sent_count      = Outbox.all(:processed => 1).count
  @scheduled_count = Outbox.all(:error => -1).count
  @errored_count   = Outbox.all(:error.not => [-1,0])

  erb :your_template
end

If you're going to load these over multiple pages, there's also before

before(/this|insane|regexp|to|grep|locations/) do
  # assign variables
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top