Skip to content

Instantly share code, notes, and snippets.

@clamstew
Last active August 29, 2015 13:56
Show Gist options
  • Save clamstew/9119151 to your computer and use it in GitHub Desktop.
Save clamstew/9119151 to your computer and use it in GitHub Desktop.

Partner Exercise 4:

**View concepts we will cover: **

  • more practice with the Foundation CSS framework and writing minimal layout css
  • using partials to encapsulate parts of your layout
  • using partials and passing in local variables for repeating elements
  • using font-awesome icon set for rapid prototyping

Now it's time to turn all that great data into something more "web-appy".

**Logitstics:** Try your best to make this part of the lesson **a no copy paste zone**. This will give you a good feel for how all the pieces of the view come together. Hopefully, you also get a good feel for where to put all the files in a pretty classic Sinatra file structure, when to make partials (hint: often), and this will revisit how to construct layouts with Foundation and a minimal amount of css that needs maintaining. Also if you ever get truly lost during this walk-through, please reorient yourselves by looking at the full codebase on [github](https://github.com/clamstew/github-sinatra-feed-app). Try not to have to.
views/layout.erb

Lets start with the main application layout.erb file in your views directory. It will start with a few CDN files for Foundation, Font Awesome for icons, and jQuery. We will talk more throughout the course about why the javascript files should always go at the bottom.

Also we will link in a couple of local files stored in the public directory for custom CSS and javascript. Sinatra serves files and folders it finds in the public folder (You will find that Rails also does this).

Lastly, lets make a basic Foundation structure. We are going after this layout for the getfeed/:username/:reponame route.

Lets liberally steal a common social feed design pattern from the web:

First let's be clear. We are not taking their code. We can make this same structure with partials and Foundation pretty fast with minimal CSS. **Often when you take code from the web it is more trouble than it's worth.** And it is inherently not broken up into partials well.

Add this to your layout.erb file:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>The Repo Feeder</title>
        <link rel="shortcut icon" href="/images/feedIcon.png" type="image/x-icon" />
        <link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/foundation/5.1.1/css/foundation.min.css">
        <link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
        <link rel="stylesheet" href="/application.css" type="text/css" />
    </head>
    <body>
        <header class="row">
            <%%= erb :_header %>
        </header>
        <section class="row">
            <div class="large-3 columns">
                <%%= erb :_user_info %>
            </div>
            <div class="large-6 columns activity-feed">
                <%%= yield %>
            </div>
            <div class="large-3 columns">
                <%%= erb :_ads_left_column %>
            </div>
        </section>
        <footer class="row">
            <%%= erb :_footer %>
        </footer>
        <script type="text/javascript" src="//cdn.jsdelivr.net/jquery/2.0.3/jquery-2.0.3.js"></script>
        <script type="text/javascript" src="/application.js"></script>
        <%%# possibly add in foundation js here - not necessary %>
    </body>
</html>

In the <body> tags, we put in a <header> and <footer> tag that merely create Foundation "row" and set up a place for us to put in the erb partials to the other files. We can go ahead and create those files (_header.erb and _footer.erb) in the view folder. The underscore is merely a file naming convention for partials. (This should also keep those partials from ever being loaded in the browser by themselves.)

Next, focus on the vertical middle section between the <header> and the <footer>. The meat of the layout.

Again we will start by making a 12-column foundation class="row" on the middle <section> tag. We want 3 columns for the two sidebars with the bigger middle of 6 columns. So to say it another way we need to add 3 columns on the left for the profile, 6 columns in the middle for the feed and for any parts of the app that I want to pull in, and 3 columns on the right side for the ads.

Also go ahead and create the files for those partials in your view folder: _user_info.erb and _ads_left_column.erb. We will start filling in all these partials in a second, but notice that we are leaving the middle column open for whatever erb the main server.rb file gives us for the given route we are on, such as erb :feed with the <%= yield %> code. So we can use this for other routes like creating a post route so we can search for another repo.


Header and Footer

Lets visit the header and footer partials and put in some code.

Header:

<div class="large-8 columns">
  <h1><i class="fa fa-rss-square"></i> The Repo Feeder</h1>
</div>

<div class="large-4 columns">
  <p class="repo-name">
    <i class="fa fa-github"></i> <strong>Repo:</strong> <a href="http://github.com/<%%= params[:username] %>/<%%= params[:reponame] %>" target="_blank">
      <%%= params[:username] %> / <%= params[:reponame] %>
    </a>
  </p>
</div>

<hr />

And the Footer:

<hr />
<h1>Thanks for feeding!</h1>


Then let's put in some code for those sidebars, and lastly we can focus on the feed:

Here is the profile sidebar

<%%# if the user info is empty put in the dummy sidebar to impress the UI team %>
<%% if @user_info.empty? %>
  <img src="http://placekitten.com/g/200/300" />
  <h3>Dummy User</h3>
  <p>
    <strong><i class="fa fa-envelope"></i> Email</strong>
    <a href="mailto:[email protected]">[email protected]</a>
  </p>
<%% else %>
  <%%# implement your own code to pull in a user's profile data here %>
<%% end %>

And here is some dummy ads (bonus points for DRYing up this code! ... any repeating code should really start to scare you):

<div class="ad-wrapper">
  <h5>
    <i class="fa fa-tags"></i> Buy This!
    <a href="#" class="closer"><i class="fa fa-power-off"></i></a>
  </h5>
  <img src="http://placehold.it/220x240&text=[ad]" />
  <br clear="all" />
</div>
<div class="ad-wrapper">
  <h5>
    <i class="fa fa-tags"></i> Also Buy This!
    <a href="#" class="closer"><i class="fa fa-power-off"></i></a>
  </h5>
  <img src="http://placehold.it/220x240&text=[ad]" />
  <br clear="all" />
</div>
<div class="ad-wrapper">
  <h5>
    <i class="fa fa-tags"></i> Don't forget about this!
    <a href="#" class="closer"><i class="fa fa-power-off"></i></a>
  </h5>
  <img src="http://placehold.it/220x240&text=[ad]" />
</div>

Now for the meat and potatoes ... Let's 'feed' this machine

Here is some code for the feed:

<%% @commits_hash.each do |c| %>
  <%%= erb :_feed_item, locals: {commit: c} %>
<%% end %>

Since the server.rb file passes to feed.erb, we won't consider it a partial in the views folder (and not use the partial _partialname.erb naming scheme ). This is certainly debatable - remember with partials and CSS: you are creating your own craziness to have to maintain.

We are doing something neat here. We are essentially using partials to template inside of an erb each loop. So each time it loops through the @commits_hash array, it passes in a local variable called commit to the _feed_item.erb partial. The local key commit takes in the commit object that is assigned to the value of c.

So now we just need 1 of those feed items as a template for all of them.

Code for _feed_item.erb:

<div class="row feed-item">

  <div class="large-3 columns">
    <a href="http://github.com/<%%= commit["author"]["login"] %>" target="_blank">
      <img src="https://secure.gravatar.com/avatar/<%%= commit["author"]["gravatar_id"]  %>" />
    </a>
  </div>

  <div class="large-9 columns">
    <div>
      <strong>Author:</strong>
      <a href="http://github.com/<%%= commit["author"]["login"] %>" target="_blank">
        <%%= commit["commit"]["author"]["name"]  %>
      </a>
      <br />
    </div>
    
    <div>
      <strong>Commit Message:</strong> <%%= commit["commit"]["message"]  %>
      <br /><br />
    </div>
    
    <div>
      <i class="fa fa-code"></i><a href="<%%= commit["html_url"]  %>" target="_blank">View Commit Diff</a>
      <span style="float:right;"><strong><small><i class="fa fa-clock-o"></i> <%%= DateTime.iso8601(commit["commit"]["author"]["date"]).strftime("%m/%d/%Y at %I:%M%p") %></small></strong></span>
    </div>
  </div>

</div>

This is still using many foundation column layout principals, by creating a new 12 column row inside of the 6 columns in the middle. Then we create 3 and 9 columns so the profile picture is held on the left and we can pull in items like the user's name, commit message, link to the git diff, and time-stamp on the left side. (Bonus points for fixing the inline style on the timestamp. Also look at the ruby docs for what you can do with string of time.)


Lastly, lets add some styles to pretty it up.

In application.css in the public folder, add in these styles one at a time and think about what they are doing. Also feel free to give this your own twist.

/* Application specific CSS */

/* make the background grey */
body { background: #eee; }

/* move the repo name down from the top - move over vertical-align! */
header p.repo-name { margin-top: 30px; }
/* make the main logo mks blue */
header h1 {
  color: #1189d9;
  text-shadow: 2px 2px 2px #FFFFFF;
}

/* nice little feed boxes in the middle column */
.feed-item {
  background: #fff;
  padding: 20px 0;
  /* make the border pretty */
  box-shadow: 0 1px 1px rgba(0,0,0,0.2);
  -webkit-border-radius: 2px;
  -moz-border-radius: 2px;
  border-radius: 2px;
}

/* spread out the feed boxes */
.row.feed-item { margin-bottom: 10px; }

/* put some space between the code icon and the link to diff */
.feed-item i.fa-code { margin-right: 10px; }

/* put the closer X in the top right of the ad */
.closer { float: right; }

/* center the text in the footer */
footer h1 { text-align: center; }

And for good measure make sure you have a favicon in the public/images folder, so that the link in the <head> tag has something to grab. It an really be any png that is around 32 by 32. If you call it feedIcon.png, then you don't have to adjust the file name in the <head> tag.


Also this site doesn't move yet. Let's at least sprinkle on one jQuery event.

Go to application.js file and add:

// Application specific JS

// set up an ad closer click handler
// that slides up the add on click
$(".ad-wrapper").on("click", ".closer", function(e){
  e.preventDefault();
  $(this).parents(".ad-wrapper").slideUp();
});

This will allow the user to hide the ads on the left side by clicking the on/off icon.

That is about it for the layout at this point. Especially in the extensions start to make this site your own.

By adding in a couple input boxes and a submit button at the top of the feed 6 columns, you can post to another route with the same structure post '/feed/:username/:reponame', you can then have another erb file like post_feed.erb. Then you can use the same partials you already have to print out a brand new repo that is sent through the <form>. Happy view script hacking!


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment