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

Alrighty then. Where were we? I believe we left off in a good place. We installed the webpacker gem, and seemed to have communication between our newly created JS file and our app. Now for the hard part. I’m still learning this stuff myself, so bear with me. We’re going to attempt to use ES6 modules instead of the old way of declaring AngularJS components and such. This style guide is a good starting point to get to know what your components will look like and how they’ll interact with each other.

Setting up the Main Module

The first thing we’ll want to do is setup up our main Angular module in app/javascript/packs/application.js. First we have to import angular into the file so our module knows what it’s attaching itself to. We are also going to export the module, which will allow our webpack to compile it when we run app in the terminal.

// app/javascript/packs/application.js

import angular from 'angular';

const meals = angular.module('meals', [])

export default meals;

Now we have to declare our app in our main html file: app/views/layouts/application.html.erb. So in the body tag, add ng-app=”meals”.

<!DOCTYPE html>
<html>
  <head>
    <title>Meals</title>
    <%= csrf_meta_tags %>

    <%= stylesheet_link_tag    'application', media: 'all' %>
    <%= javascript_include_tag 'application' %>
    <%= javascript_pack_tag 'application' %>
  </head>

  <body ng-app="meals">
    <%= yield %>
  </body>
</html>

Now our app knows that it’s an Angular app and it’s looking for a module called ‘meals’. Let’s add a route with a component so we can actually see something working on the Angular side of the world.

Routing With angular-ui-router

If you’ve built anything with Angular in the past, you’ve most definitely used angular-ui-router. We’re going to install it with yarn. If you don’t have yarn installed, check out the installation instructions here. To install, or ‘add’ as it’s called in yarnish, head over to your terminal and type: ‘yarn add angular-ui-router’. If you check your dependencies in your package.json file, you should see ‘angular-ui-router’ listed.

So let’s see if we can get a route working. In our angular_home.html file, let’s add a ui-view directive.

<-- app/views/application/angular_home.html -->

<ui-view></ui-view>

This will give us an entry point into AngularLand and let us declare routes with $stateProvider in a config function. Back in our application.js file, let’s add a config function and a route. First we’ll have to import the ui-router so we can use all of its goodness. Check it…

// app/javascript/packs/application.js

import angular from 'angular';
import uirouter from 'angular-ui-router';

const meals = angular.module('meals', [uirouter])
  .config(($stateProvider) => {
    $stateProvider
      .state('home', {
        url: '/',
        template: `<h1>Hola Mundo!</h1>`
      })
  })

export default meals;

Ok so here we’re importing the angular-ui-router and chaining a config function onto our module. Angular-ui-router gives us access to $stateProvider, $urlRouterProvider, $state, and $stateParams. In the config function above, we’re using the Arrow function syntax now available in ES6, and setting the state. With a url and a simple template, we should be getting somewhere. Let’s quickly make a link back in angular_home.html so we can see our route is working.

<-- app/views/application/angular_home.html -->

<a ui-sref="home">Home</a>
<ui-view></ui-view>

Run the Webpack and Rails Server Simultaneously?

Now to run webpack, we can’t just run the rails server. We actually have to run the rails and the webpack servers. Back in the terminal, create a new tab in the same directory, then run ‘./bin/webpack-dev-server’. This will compile your included javascript files through webpack. If you’re like me, then you probably got a lot of red errors followed by this line: webpack: Failed to compile.

So something is not letting us load our module. If we scroll up in the terminal, we’ll see that most of the errors say that angular doesn’t exist. But I thought we installed Angular already!! Well, I’m pretty sure that when we installed it with the webpacker command, it installed Angular 4. We need version 1.5.8, which we can easily install add with yarn. Exit out of the webpack server in your terminal. Then type ‘yarn add angular@1.5.8’.

Check out your package.json file and you should see angular with the correct version listed under the dependencies. Now if we try to run the server again – ‘./bin/webpack-dev-server’ – everything should compile (there might be a few warnings, but let’s not worry about those). In your other tab run the rails server command and in your browser go to ‘localhost:3000’. You should see a link that says ‘Home’. Click it, and you should be routed to the home route that we set up earlier. If you followed along, you should see ‘Hola Mundo!’ on the webpage!

To Sum it Up

We are in the Angular business now! In this episode, we’ve connected the front end to our meals app with webpack, added angular-ui-router and AngularJS, created our main module with a route and template, learned how to run the webpack server, and saw our template working in the browser. Next time, we’ll get some functionality going with some http requests to the backend and do something a little more exciting than Hello World Hola Mundo. As always, thanks for reading. I hope this helps someone out there! Until next time…CHEERS:)

Advertisements

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:)

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

In my last post, I wrote about using Webpack with Rails and AngularJS, and how it differed from using Bower. There is definitely a bigger learning curve using Webpack, but I believe it will all be worth it when the dust settles. Besides, it seems that Bower has been deprecated. I’m going to try my hand at a tutorial using these three technologies and share my confusion as we go. ES6 syntax will be used in Angular also, which changes how we write our components. Let’s dig in.

The Setup

I’ll assume that you have Rails installed already. We’re going to build a simple CRUD app using Rails as an API on the back end, and AngularJS on the front end and Webpack to bridge the two. We’re going to build a Meals app, with a users table and a meals table. It’s simple but what we want out of this is to be able to use these technologies together – then we can start adding complexities.

‘cd’ into you directory of choice and start a new rails app:

rails new meals --skip-turbolinks

We’re skipping turbolinks because it can cause trouble with Angular. Now that the basic Rails skeleton is created, ‘cd’ into ‘meals’ and open Atom (or your text editor of choice). The version of Rails I’m using is 5.0.6. I’m using the built-in database – sqlite3 – because using Postgres would be adding another complexity to this that we don’t need. Let’s make our first commit to github. I’ll assume you know how to start a repo.

git add .
git ci -m 'initial commit'
git remote add origin https://github.com/SiamKing/meals.git
git push -u origin master

Now let’s create our models. I usually don’t use ‘scaffold’ to generate my models because it adds so much bloat to Rails, but I’m going to use it because it’s so easy – that’s what we’re going for.

rails g scaffold user name:string
rails g scaffold meal title:string
rails g model user_meal user_id:integer meal_id:integer
rails db:migrate

Like I said – super basic. Now that the databases are created, let’s enter the rails console in the terminal and create our first user and meal.

rails c

User.create(name: 'Allison')
Meal.create(title: 'Pizza')

As long as we migrated our database, these commands should work, which means we’ll have our first user and meal. Now we have to think about the association between these two tables. Well, users have many meals and meals have many users. So, it’s a has many to has many relationship. Let’s go into our models and add the associations.

class User < ApplicationRecord
  has_many :user_meals
  has_many :meals, through: :user_meals
end

class Meal < ApplicationRecord
  has_many :user_meals
  has_many :users, through: :user_meals
end

class UserMeal < ApplicationRecord
  belongs_to :user
  belongs_to :meal
end

Let’s try to add a meal to our first user…

rails c

UserMeal.create(user_id: 1, meal_id: 1)
# created an association in our joins table for the first user and first meal

User.first.meals
# Now we can see the first users meals
=> #<ActiveRecord::Associations::CollectionProxy [#<Meal id: 1, title: "Pizza", created_at: "2017-09-17 22:51:13", updated_at: "2017-09-17 22:51:13">]>

Alright! Our models are working as they should, so the next step is to serialize our models into an API so they can be consumed by our front end. We’ll use the wonderful Active Model Serializers for this. Of course there’s a gem! Add this line to your gem file:

gem 'active_model_serializers', '~> 0.10.0'
bundle install

Now let’s create our serializers.

rails g serializer user
rails g serializer meal
rails g serializer user_meal

This generated serializers for our three models. Let’s add our associations.

class UserSerializer < ActiveModel::Serializer
  attributes :id, :name
  has_many :user_meals
  has_many :meals, through: :user_meals
end

class MealSerializer < ActiveModel::Serializer
  attributes :id, :title
  has_many :user_meals
  has_many :users, through: :user_meals
end

class UserMealSerializer < ActiveModel::Serializer
  attributes :id
  belongs_to :user
  belongs_to :meal
end

Now we have our associations set up. Let’s run our local server and see what we have. Run ‘rails s’ in your terminal and go to ‘http://localhost:3000/users/1.json&#8217; in your browser. This should give us our first users information in JSON format. It should look something like this:

{
id: 1,
name: "Allison",
created_at: "2017-09-17T22:50:16.012Z",
updated_at: "2017-09-17T22:50:16.012Z",
url: "http://localhost:3000/users/1.json"
}

Ok that’s cool, we have some JSON! The only thing is we can’t see our user’s meals. Let’s fix that! Open up your users controller and add this to you show method:

if @user
  render json: @user, include: { meals: [:title] }
end

Now refresh your browser and voila!

{
  id: 1,
  name: "Allison",
  meals: [
 {
    id: 1,
    title: "Pizza"
  }
  ]
}

Sweet! We can see our associations! Our back end is fully functional and is set up as an API. This JSON formatted information can now be consumed by our front end. This concludes the first part of this series. I’ll be back next week for part 2. We’ll get our hands really dirty setting up Webpack and Angular. Until then…Cheers:)

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:)

Using ES6 Syntax in React

I don’t know about you, but I love the changes made in ES6. I’m currently learning React and ES6 definitely makes life much easier. I’ll talk specifically about Arrow Functions and why using them will help make you coding your components much more fun.

The Olde Way

Let’s take a look at a simple pre-ES6 component.

import React from 'react';

class WhatsUp extends React.Component {
  constructor() {
    super();
    
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick(event) {
    // 'this' is only reachable because of the binding in the constructor above
    // otherwise it would be scoped to handleClick's environment and the log 
    // would be undefined 
    console.log(this.props.message)
  }

  render() {
    return (
      <button onClick={this.handleClick}>Click Me</button>
    )
  }
}

export default WhatsUp

The main takeaway here is the binding of the ‘this’ keyword. Without the binding in the constructor, when we used ‘this’ inside of a function, it would be referring to the functions ‘this’ – not the class.

How the Cool Kids Are Doing It

The cool thing about Arrow Functions is that they don’t bind their own ‘this’. What do the Gods say?

From our friends at Mozilla:

An arrow function expression has a shorter syntax than a function expression and does not bind its own this, arguments, super, or new.target.

Until arrow functions, every new function defined its own this value (a new object in the case of a constructor, undefined in strict mode function calls, the base object if the function is called as an “object method”, etc.). This proved to be annoying with an object-oriented style of programming.

That means we don’t have to worry about binding the function in the constructor. Take a looksie…

import React from 'react';

class WhatsUp extends React.Component {

  handleClick = (event) => {
    // 'this' is not bound to the handleClick function so we can use it freely
    console.log(this.props.message)
  }

  render() {
    return (
      <button onClick={this.handleClick}>Click Me</button>
    )
  }
}

export default WhatsUp

Look at that – we don’t have to use a constructor! Pretty cool. You might think, ‘Eh, no biggie’. But what if we had many more functions that we had to bind ‘this’ to? That’s much more code we have to write and makes our files more bloated. I know if we had to set an initial state, we’d still have to write a constructor. However, we wouldn’t have to bind so many functions.

If you haven’t started using ES6, I strongly recommend it. It will save time and energy in the long run. The Spread Operator is probably what I use second most, after Arrow Functions. Try them out and be amazed! Until next time. Cheers:)