Rails, AngularJS (1.5.8), and Webpack — Part 2

Welcome back! We left off last time in a good place. We set up the back end by generating three models – User, Meal, and UserMeal (our joins table) – with associations. We used scaffolding to generate our models. In most cases, we would normally not generate models using scaffolding, because it creates a lot of things we won’t need. This causes bloat in our app, and if we want our app to scale nicely and be fast, this will be a problem. For our case (and our little app), it’s nice and easy to use scaffolding – so we did. Then we installed a great gem called Active Model Serializer, which formats our model data into reusable JSON, which our front end will consume. In this edition we’ll be installing AngularJS and Webpack. Let’s dive in.

Webpacker

A few blog posts ago, I wrote about Rails and the Webpacker gem. The team at Rails is definitely catching on to the current and future trends of the web – front end frameworks using JavaScript. The Webpacker gem makes it easier to use these frameworks with Rails. Enough talk though – let’s install it! Note – if you’re using Rails 5.1, you can run ‘rails new myapp –webpack=angular’ when initiating your app. Otherwise…

# In your gemfile.rb file, add 

gem 'webpacker'

# Back in your terminal

bundle 
bundle exec rails webpacker:install

# if you get an error that looks like this: 'Webpacker requires Yarn >= 0.25.2 
# and you are using 0.24.6
# Please upgrade Yarn https://yarnpkg.com/lang/en/docs/install/'
# do this:

npm install -g yarn

# if everything is honky dory

bundle exec rails webpacker:install:angular

Now we’re in the webpack business. Using webpack basically creates another asset pipeline for our JavaScript assets. Instead of putting all of our JavaScript files in /app/assets, we’ll put them in app/javascript/packs. To include this folder, all we have to do is include them in our main html files ‘head’ section.

# app/views/layouts/application.html.erb

<%= javascript_pack_tag 'application' %>

Now our files will be included and we can get coding. Let’s create the entry point to the angular app. Create a new folder and file in our views folder:
app/views/application/angular_home.html. Now we need a route. Let’s add it to our routes.rb file.


root to: 'application#angular_home'

Let’s add something to our angular_home file.

# app/views/application/angular_home.html

Goodbye World

# LOL?

Now run ‘rails s’ in your terminal and head on over to ‘locahost:3000’ in your browser. We should see ‘Goodbye World’ on the webpage. Now look in the console (Apple Control ‘J’) and you should see ‘Hello World from Webpacker’. We’re in business.

I think this is a good place to leave off. Our backend is set up. Webpack is setup. We have an entry point to Angular. Things are looking good. Next week we’ll dive head first into Angular. Working with modules and all the goodness that comes with ES6! Until then…cheeeeeers:)

Advertisements

Rails, AngularJS and Webpack – First Impressions

I recently started learning React because it seems like it’s the new ‘it’ technology in town. My previous front end framework knowledge was limited to AngularJS. It took me some time to like it, but eventually I did. I might have an interview soon and the technologies the company uses are mainly Rails and AngularJS(v1.5). This has made me go back to Angular and start building again. It’s amazing how fast information leaks out of ones head.

The first thing I noticed when starting a project was that Bower has been deprecated. I knew that Bower was on its way out when I learned AngularJS, but that was only a few months ago. Things certainly change fast in the world of technology.

Note to self: don’t get too comfortable with any technologies you use.

So what to do? How should I handle my front end dependencies? There are many ways, some of which are already on the outs too – like Gulp. After doing some research it seems like the wave of now and the near future is Webpack. Even Rails is getting in on the action by including it with Rails 5.1. Rails is still in heavy use in the industry, however has seen some decline from the glory years. Most of the decline in usage has to do with all of the front end technologies that have sprouted up in the last five years. Rails was not keeping up with the trends and Rails’ dependency on the Asset Pipeline – once the best thing since sliced bread – was now hindering development.

Well, guess what? The team behind Rails has finally caught on and the inclusion of the Webpacker gem is a huge step in the right direction. I could see a big boost in Rails usage as a result. That’s great and all, but what does Webpack actually do? From the Webpack github page:

webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.

When using Rails, it basically creates another asset pipeline for JavaScript files. Whenever learning something new, there will be a learning curve and some frustration involved. In my case, using Rails 5.0.1 and AngularJS(1.5.8), there has definitely been a bit of both. Especially since there’s not much documentation or tutorials for the versions I’m using. I’m finally making some headway and actually have a basic app running in my browser. There’s much more importing of files and such going on, which I became familiar with through React. This week I’m going to become much more familiar with the inner workings.

My next blog post will be a tutorial on getting Rails(5.0.1), AngularJS(1.5.8) and Webpack to all play nice together. Have you built anything with these technologies? Please comment below, I’d love to hear about it! Until next time…Cheers:)

Removing whitespace from a string in Ruby vs. JavaScript

I’m back from vacation. After visiting my family in Long Island, we ventured up to the Catskills for a few nights, which culminated with my younger sister getting married. It was a very cool wedding! The next day, my wife, nephew, and I drove up to Montreal to see her folks. Montreal is one of my favorite cities (in the summer) – it has very European feel. As great as it is to get away, it’s always hard to get back into the groove after a trip. I’m just getting my sea legs back under me so this post is going to be short and sweet.

Have you ever needed to get rid of leading and trailing whitespace from a string? It’s a good rule of thumb to do just that to any input you’re receiving on a form. Luckily, it’s quite easy in most languages. Let’s take a look at how we’ll approach this in Ruby first.

str = "  How's it going?   "
=> "  How's it going?   "
# Let's get rid of that whitespace
str.strip()  
=> "How's it going?"
str 
=> "  How's it going?   "
# We didn't permanently change the string itself
# Most methods are non-destructive, but Ruby let's us be destructive if we 
# really want to. We just got to bang it (pun intended)
str.strip!() 
"How's it going?"
str 
=> "How's it going?"

Pretty simple! Let’s take a look at how to do this in JavaScript.

let str = "  How's it going?   ";
str.trim(); 
'How/'s it going?'
str  
'   How\'s it going?   '
// There's no permanent destructive way to change strings in JavaScript - they 
// are immutable. So we just have to reassign our variable like so...
str = str.trim();
'How\'s it going?'
str  
'How\'s it going?'

I mentioned that strings in JavaScript are immutable. This means the string cannot be changed in memory. So when we call a method like trim or slice on a string, the return value is a new string. Like the example above, we have to reassign ‘str’ to the return value of the method call. In Ruby however, strings are mutable. Let’s take a look.

str = "  Trim me  "
str.object_id 
=> 70365544319940 
str.strip!()
=> "Trim me"
str.object_id
=> 70365544319940 
# Even though we changed the string, the id is still the same
# We can also change characters in place, which cannot be done in JS
str[7] = '!'
=> '!'
str
=> "Trim me!"
# Pretty cool!
str.object_id
=> 70365544319940 
# No change

That’s it for this week. Always remember how cool Ruby can be. It makes life easier in many ways. JavaScript however, can do much more. It is not only an Object Oriented language, but a multi-paradigm language! From Wikipedia:

As a multi-paradigm language, JavaScript supports event-driven, functional, and imperative (including object-oriented and prototype-based) programming styles. It has an API for working with text, arrays, dates, regular expressions, and basic manipulation of the DOM, but does not include any I/O, such as networking, storage, or graphics facilities, relying for these upon the host environment in which it is embedded.

Thanks Wikipedia! Until next time! Cheers:)

Recursion – It’s Not a Hallucination

Does recursion scare the crap out you? Well, it should! You should stop reading this now, draw the blinds, get in bed and pull the covers over your head. Just kidding! Recursion is pretty cool once you get the hang of it. I’m going to try to break it down for you so you won’t have to run and hide every time it’s mentioned.

From Wikipedia:

Recursion in computer science is a method where the solution to a problem depends on solutions to smaller instances of the same problem (as opposed to iteration). The approach can be applied to many types of problems, and recursion is one of the central ideas of computer science.

Okay, so basically it is a problem that can be broken down into smaller versions of itself. This happens when a function gets called repeatedly by itself until it reaches the stopping point, which is called the base case. So a recursive function is a function that calls itself. Every time the function calls itself, it is looking for the base case. If the base case is not found, the function calls itself again. If you think about it too long, it might make you feel like you’re hallucinating. And down the rabbit hole we go…

Think of it like a for loop, except that the function is sort of flying blind until it reaches the base case.

Enough talk, let’s see an example.

function multiplyUpToFive() {
  // (1 * 2 * 3 * 4) * 5 or
  return multiplyUpToFour() * 5;
}

function multiplyUpToFour() {
  // (1 * 2 * 3) * 4 or
  return multiplyUpToThree() * 4;
}
// and down to multiplyUpToOne()

What we’re doing here is breaking down the problem into smaller problems. That wasn’t a recursive function, but it acts the same way a recursive function does. I’ll rectify this further on. Now for our recursive function, by taking function called multiplyUpTo(n), you can say that the definition of the function is equal to taking the product of

  • the products up to n – 1
  • times n
  • Let’s see…

    function multiplyUpTo(n) {
      return multiplyUpTo(n - 1) * n;
    }
    
    // let's call this with an argument of 4 and see what happens
    
    multiplyUpTo(4)
    multiplyUpTo(3)  // gets called
    multiplyUpTo(2)  // gets called
    multiplyUpTo(1)  // gets called
    multiplyUpTo(0)  // gets called
    multiplyUpTo(-1) // gets called
    // shiiiiiit. Looks like we might be stuck in a recursive loop forever!!!
    

    That function would have ran infinitely because we didn’t add a base case. Think of the base case as the roof of the function. Without it the function will keep going out into space – to infinity and beyond! There’s literally nothing to stop it. Okay, enough analogies. Let’s fix our multiplier function.

    function multiplyUpTo(n) {
      // Our base case is 1, so we'll check if n equals 1
      if (n == 1) {
        return 1;
      }
    
      return multiplyUpTo(n - 1) * n;
    }
    
    // Now if we call our function with 4 as the argument, this is what will happen
    
    multiplyUpTo(4)
    // n does not equal 1, so it's called again
    multiplyUpTo(3) * 4
    // Again n does not equal 1
    multiplyUpTo(2) * 3
    multiplyUpTo(1) * 2
    
    // We reached our base case which is 1 and our function will not repeat forever 

    Now our function knows where it is in the universe and has found its purpose in life.

    Okay, the function has purpose. Now what?

    // Once the function reaches the base case, it will now solve all of the
    // problems it left behind
    
    multiplyUpTo(1) * 2 // 1 * 2 = 2
    multiplyUpTo(2) * 3 // 2 * 3 = 6
    multiplyUpTo(3) * 4 // 6 * 4 = 24
    
    // Once the function has an answer to all of itselves (I think I made that up),
    // then it returns the product the original function call. Woah dude.
    

    If we’re feeling good about our JavaScript we can even use a ternary statement to really make our function compact.

    function multiplyUpTo(n) {
      return n == 1 ? 1 : multiplyUpTo(n - 1) * n;
    }
    

    I like it! Thinking recursively makes you think recursively makes you think recursively. See what I did there. Yeah, I’m a dork. Hopefully this helped you understand the world of recursion. It’s quite fun to write algorithms this way. Although it might be scary at first, don’t worry: The worst that can happen is you float away into the infinite:)

    How to Clone a Website Using Chrome’s Dev Tools Part I

    Ever want to copy a website? Well, it’s pretty easy – especially with Chrome’s Dev Tools! I find it pretty useful to go into someone else’s code to see how they’re doing what they’re doing. Then you can implement new cool features for sites you’re working on. I’m not going into complicated websites with API’s and the like; just a simple static site.

    I’m going to be using Carbon Five’s website as reference. First head on over there, then right click on the page and select ‘view page source’. This will show us all the html for the page. Now just select all (command + ‘a’) and copy. In your text editor of choice (I’m using Atom), create an index.html file and paste the html there. You’ll see a bunch of files that are referenced in the ‘head’ of the document. We’ll have to copy the non-CDN local files into our text editor.

    We’re going to open each file from the page source and copy file into our text editor.

    Screen Shot 2017-07-02 at 3.41.31 PM

    Create folders for each type of file, ie. javascripts, stylesheets, images, etc. We’re going to do what we did above when copying and pasting all of the HTML. Starting from the ‘javascripts/showup.js’ file in the head of the view source page document, click on each file, select all, copy (noticing a trend?) and paste into a newly created file in Atom. Name the file the same as the file you’re copying from. From here, let’s see where we stand by opening the index.html file in Chrome. Go ahead, I’ll wait…

    Screen Shot 2017-07-02 at 5.24.47 PM

    It should look something like this

    Woah! All of a sudden we’re in 1995 and Nirvana’s on the radio! We’re getting the bare bones HTML here. Let’s take a look in the console to see what’s going on under the hood. Command + option + ‘j’ will get us there. Notice all of the errors.

    Screen Shot 2017-07-02 at 5.30.38 PM

    That’s a lotta red

    There are a ton of files that can’t be found. There are definitely some files we haven’t looked at yet, but let’s focus on the ones we have. Our file directory must be different than Carbon Five’s. All we have to do is reference them a bit differently than we are.

    Let’s look at the non-CDN files in the ‘head’ of our index.html page. They all start with a forward slash, but if we’re referencing from the index.html file, we’ll have to prepend them with a single period to jump up to the root directory. Start from the ‘showup.js’ file start adding.

    <script type="text/javascript" src="/javascripts/showup.js"></script> // This
    // Turns into 
    <script type="text/javascript" src="./javascripts/showup.js"></script>
    

    When you’re done (remember to save), refresh your index.html file in Chrome. You’ll notice a few things happened. The page has some styling now – not great, but it’s something. Next, we have less errors in the console. Sweet! Let’s keep going and turn these errors green.

    In the console, notice how the cdn files which can’t be found start with two forward slashes. Since they are referencing outside websites as opposed to local files, we’ll have to prepend them with ‘https:’, and they should be good to go. Back in our index.html file, let’s do just that. Once you’re done, notice how the links turn blue. We now have good links. Go back to your browser and refresh.

    Screen Shot 2017-07-02 at 5.41.40 PM

    Getting there!

    Now we’re talking! Since we’re now referencing the bootstrap cdn files correctly, we have our navbar looking good and the page layout is looking much better. Next time, we’ll add images and conquer any other errors we come across. Until then, CHEERS:)

    I’ve Got 99 Problems – but Deploying My Rails/Angular App to Heroku is No Longer One of Them:) PART 2

    So where was I? Oh yeah, I left off at changing my problem js file extensions to ‘.es6’ so there would be no problem with new JS6 syntax. This definitely helped, but in it’s place sprung another problem. Only the images that were not hooked up to the database on my site were showing . So I used my noggin and realized that I never migrated my database to Heroku! DOH!

    When I tried to run ‘heroku run rake db:migrate’, the migration kept aborting with this message:

    PG::UndefinedTable: ERROR:  relation "users" does not exist
    

    I definitely had a table called “users” so that didn’t make much sense. I did a little digging and found out that postgres (the database Heroku uses) does not like tables relating to other tables that have not been created yet. The table being created was referencing a table that was created on a later migration. I know it’s not a good idea to mess with the names of migration files, but I did anyway. Rails timestamps migration files, so I just had to change my “users” file timestamp to a date before the file in question.

    So I tried the migrate command again and got the same error. Strange. My migration files had quite a few additions which later became subtractions. I decided that I only really needed three migrations for three tables. Since I had a good seed file which could recreate everything I needed, I decided to recreate only the migrations I needed. This would allow me to reset the database and start from scratch. I deleted the schema and development.sqlite3 files so there would be no references to the old migrations. Now I could recreate my database and schema file.

    $ rails db:drop db:create db:migrate db:seed
    // This will delete the entire database, losing all data
    // recreate a new database and runs the migrations
    // db:seed will seed the database from seeds.rb
    

    I had a brand spanking new schema and database, ran my local server and everything was running smoothly. So I ran the heroku migration command again and got THE SAME ERROR!! WTF?!? After googling for a bit, it hit me. I didn’t push the new changes to heroku! Often times it is the simple tasks that one might forget to do that causes errors. Note to self: if you are banging your head against the wall, stop for a minute and think of the steps you would normally take. Save yourself some time and energy. The first change to the “users” migration file name probably would have worked if I just slowed down a little.

    After trying to migrate to Heroku again, it worked! Now my site is up and running, and I’m feeling good! Hopefully this helps fellow programmers out there that get stuck – and have sore heads! As always, thanks for reading!

    AngularJS: Filter – Behind the Scenes

    AngularJS comes with a ton of built in features to help us out – meaning we don’t have to reinvent the wheel every time we want to do something. This makes it extremely easy to do things such as searching or filtering. However, sometimes it’s a good idea to check what’s going on under the hood, which can only help us in the end. These helpers are great, but if you’re knew to programming, they could stunt your growth as a developer. So let’s dive in.

    I built an app called Medidate. It’s a simple (a lot of hours goes into simple!) single page app that keeps track of meditation sessions: the date, which kind of meditation, and the duration. It uses Rails as an API on the back-end and AngularJS on the front-end. I’m going to go over a sorting feature that could easily be implemented with Angular’s built in Filter helper. Here’s a Plunker with the easy way.

    The Easy Way

    Here’s some of the code…

        <div ng-controller="UsersController as vm">
          <div class="container">
            <div class="col-md-3 col-md-offset-9 dropdown-meditation">
              <div class="button-group">
                <select class="btn btn-default btn-md dropdown-toggle dropdown-text"
                  ng-model="vm.option">
                  <option value="" disabled selected>Sort Events By</option>
                  <option value="date">By Date (Asc)</option>
                  <option value="-date">By Date (Desc)</option>
                  <option value="meditation.name">By Meditation</option>
                  <option value="minutes">By Minutes</option>
                </select>
              </div>
            </div>
            <br>
            <div ng-repeat="event in vm.user.events | orderBy: vm.option">
              <p style="text-decoration: none">{{event.date | date: medium}} for {{event.minutes}} minutes &mdash;
            {{event.meditation.name}}</p>
            </div>
          </div>
        </div>
    

    To give a bit of background, the information that’s being sorted here is an array of user events. The user has many events, which have the date, minutes, and a nested association of meditation, with id and name. This was all produced from an $http call to the back-end which was serialized into JSON by active model serializer – a very helpful gem for Rails.

    Notice the dropdown and how we’re listing the options. The values of the options are bound to vm.options. All we have to do is declare vm.option = ” in the controller and when the dropdown is selected, vm.option will now be bound to the selected option. This will in turn set the filter in the ng-repeat. Notice the orderBy : vm.option that is declared in the repeat. This is the aforementioned built in magic of Angular. Whichever option is selected in the dropdown will change the orderBy option and effect how the list is ordered.

    But what happens when you’re asked how it works. You know, like if someone asked you the what happens when you press the gas pedal in your car?  I don’t know, it just goes!

    This is when it gets interesting. Getting your hands dirty.  Instead of using filter in the ng-repeat as above, we’re going to leave ng-repeat alone, with no orderBy filter! The hard work is going to be done in the controller. Check it.

    The Hard Way

    Here’s the  dropdown and ng-repeat…

        <div ng-controller="UsersController as vm">
          <div class="container">
            <div class="col-md-3 col-md-offset-9 dropdown-meditation">
              <div class="button-group">
                <select class="btn btn-default btn-lg dropdown-toggle dropdown-text"
                        type="button" 
                        ng-model="vm.selectedOption"
                        ng-change="vm.sortBy()" 
                        ng-options="option for option in vm.options">
                  <option value="" disabled="" selected="">Sort Events By</option>
                </select>
              </div>
            </div>
            <br>
            <div ng-repeat="event in vm.user.events">
              <p style="text-decoration: none">{{event.date | date: medium}} for {{event.minutes}} minutes &mdash;
            {{event.meditation.name}}</p>
            </div>
          </div>
        </div>
    

    In the dropdown above, ng-model is set to vm.selectedOption. Now whenever the user selects an option from the dropdown, the model is now bound to the option from ng-options. The options are declared in the controller which we’ll be taking a look at soon. The straw that stirs the drink is ng-change, which fires the vm.sortBy function in the controller. Let’s take a looksie.

    .controller('UsersController', [function() {
          
          var vm = this;
          vm.sortBy = sortBy;
          vm.sortDate = sortDate;
          vm.sortMeditation = sortMeditation;
          vm.sortMinutes = sortMinutes;
          
          vm.options = ["Date (Asc)", "Date (Desc)", "Meditation", "Minutes (Asc)", "Minutes (Desc)"]
    
          function sortBy() {
            if (vm.selectedOption === vm.options[0]) {
              vm.sortDate();
            } else if (vm.selectedOption === vm.options[1]) {
              vm.sortDate();
              vm.user.events.reverse();
            } else if (vm.selectedOption === vm.options[2]) {
              vm.sortMeditation();
            } else if (vm.selectedOption === vm.options[3]) {
              vm.sortMinutes();
            } else if (vm.selectedOption === vm.options[4]) {
              vm.sortMinutes();
              vm.user.events.reverse();
            }
          };
     
    // more code below
    

    I like to bind my functions up top so I can see exactly what’s going on in the controller. This way I don’t have to search through hundreds of lines of code. Also, now we can just go ahead and write the functions as declarations, not expressions, which will save us from any hoisting headaches.

    Like I said before, when the option is selected from the dropdown, that option is now assigned to vm.selectedOption and the vm.sortBy function fires. In the sortBy function, we’ll check to see which option was assigned to selectedOption and then fire a corresponding function to sort the user.events array. Here are the missing sort functions…

          function sortMinutes() {
            vm.user.events.sort((a, b) => parseInt(a.minutes) - parseInt(b.minutes))
          }
    
          function sortDate() {
            vm.user.events.sort((a, b) => (new Date(a.date)) - (new Date(b.date)));
          }
    
          function sortMeditation() {
            vm.user.events.sort((a, b) => {
              if (a.meditation.name < b.meditation.name) {
                return -1;
              } else if (a.meditation.name > b.meditation.name) {
                return 1;
              } else {
                let dateA = new Date(a.date);
                let dateB = new Date(b.date);
    
                if (dateA > dateB) {
                  return 1;
                } else if (dateA < dateB) {
                  return -1;
                } else {
                  return 0;
                }
              }
    // end of UsersController
    

    Each function handles the data based on what the value is. Because the data in the user.events array are strings, we’ll have to convert them before sorting. The sortMinutes function is dealing with numbers which forces us to parseInt() the strings to integers. Same thing goes for the sortDate function, which we have to convert to a date before it can be sorted. Last is the sortMeditation function which takes the nested association – meditation – and sorts by name. Here we’re returning a negative 1 if the a is less, positive 1 if the b is less, and then instead of a zero if the names are the same, we’re using a sub-sort, which sorts by date.

    Here’s a working plunker of the non-magic Angular filter. I think it’s cool to look under the hood sometimes and see what all the magic is about. You never know if you’re going to learn something new – I know I did! Leave a comment below if you have any questions. Thanks for reading!