© Bryan Lim and Richard LaFranchi 2019
B. Lim, R. LaFranchiVue on Railshttps://doi.org/10.1007/978-1-4842-5116-4_2

2. Nuts and Bolts of Vue on Rails

Bryan Lim1  and Richard LaFranchi2
(1)
Singapore, Singapore
(2)
Boulder, CO, USA
 

A user interface should be so simple that a beginner in an emergency can understand it within ten seconds.

Ted Nelson

This chapter covers the attributes of a modern web application, the nature of Vue.js, choices in managing assets on Ruby on Rails, and the approaches towards integrating Vue into Ruby on Rails project. We will walk through a few examples of how to approach a Vue integration with Ruby on Rails and compare this to the traditional Ruby on Rails approach.

Attributes of a Modern Web App

A web application is one that uses web technologies, namely, HTML, CSS, and JavaScript, as the building blocks of a final software product. A web app requires some form of web-rendering technology like an Internet browser, a WebView, or any future rendering technology to display its final product.

Web apps offer the benefits of cross-platform development where a small code base can be reused across different software platforms like MacOS, Window, Linux, mobile iOS, and Android. This translates into cost saving in development budget and developer productivity at its best.

Further, some native iPhone and Android apps use a web app to form part of its entire technology stack. A mixture of web and native features within an app is called a hybrid app .

A modern web app is simply one that is using the latest–greatest web technology and is up to date with most web standards and best practices.

What Are the Attributes of a Modern Web App?

The mainstream understanding of a modern web application includes the following attributes, which we can back up by highlighting some attributes that Vue.js naturally inherits.
  • Cross platform

  • Compliance with major web browsers and web protocol

  • Simple and concise code base

  • Clean and loosely coupled architecture

  • Ease of testing

  • Flexible configurationModern UI flow that is responsive and fluid

  • Fast loading

  • Intuitive

Inherent Nature of Vue.js

Vue.js naturally fulfills the preceding attributes, and we can highlight some of the reasons why it is a great library to use in the modern Web.
  1. 1.

    Vue is highly compatible with modern web browsers. This also means it works across platforms and compliant with major web protocol.

     
  2. 2.

    Vue is fast and small in size.

     
  3. 3.

    Since Vue is only a library for building a user interface and is highly progressive, it can integrate well with any other full-web framework without creating a complex code base or architecture.

     
  4. 4.

    Vue ships with testing utilities.

     
  5. 5.

    Vue allows dynamic and responsive design.

     
  6. 6.

    Vue has the following: reactive system, data binding, virtual-DOM management, state management, and more.

     
  7. 7.

    Vue allows a component-based architecture to be integrated with any framework.

     
  8. 8.

    Vue code is intuitive to developers, so naturally it helps with building an intuitive user experience.

     

The Goodness Test

In the world of web technology, the contemporary is temporary. The modern becomes old in a year time. What we find lacking in a modern web application are similar attributes that we find in the modest and old antique furniture or old wine. The older the better. A lack of modesty in a user interface is also an unfortunate part of a modern web application where every web app aims to be overly responsive in nature. Are the preceding attributes truly a set of good gauge to define a good modern web application? Is it consistently good? Does it feel good? Is there evidence from the structure that it is good?

What makes a modern web application good is its ability to solve today’s real-world problems in a manner that is intuitive as possible to its users. On top of intuition, web applications must behave as expected, so actions produce the expected results, and it must perform quickly. In reality, the users of an application determine the Goodness Test, but as developers we want to deliver that in a way that is simple, so the tools that allow us to do this determine the Goodness Test from a developer’s perspective. Bringing in a library such as Vue into the Ruby on Rails world opens up an opportunity to revisit the tools we use for asset management that is how to manage static content such as images, CSS, fonts, and JavaScript.

Asset Management

Asset management is how we manage static files such as images, CSS, Javascript, and font files in a web application. For traditional MVC frameworks, the tools used for asset management plays an important role to faciliate the development of a modern web application. In this section, we look at some of these tools and their roles in Ruby on Rails.

Tools

Ruby on Rails uses the asset pipeline and sprockets to manage assets; we will discuss this along with Webpack and the integration of Webpack into Ruby on Rails using the Webpacker gem.

Asset Pipeline

The asset pipeline is an internal framework of Ruby on Rails to manage Javascript, stylesheets, images, and other assets. It is powered by the sprockets-rails gem. The purpose of the asset pipeline is to streamline the build process for static assets using one simple command.
rake assets:precompile

The asset pipeline has traditionally used sprockets which is a tool for compiling scss/sass files into CSS, managing the digest hashes for assets for cache busting, and using minifying/uglifying assets along with some compression techniques such as gzip.

It allows assets in your application to be automatically combined with assets from other gems. For example, jQuery-rails includes a copy of jquery.js and enables AJAX features in Rails views.

Webpack

Webpack is a module bundler for the Web that is deemed to be the future for web framework using JavaScript. Rails started a project called Webpacker, a thin wrapper around webpack together with a JavaScript package installer called Yarn, to help programmers build JavaScript app on Ruby on Rails.

Webpacker

Webpacker is a wrapper around webpack and yarn. It makes it easy to use the JavaScript pre-processor and bundler ability of webpack to manage application-like JavaScript in Rails.

It co-exists with the asset pipeline, as the primary purpose for webpack is app-like JavaScript, not images, CSS, or even JavaScript Sprinkles (that all continues to live in app/assets). However, it is possible to use Webpacker for CSS, images, and fonts assets as well, in which case you may not even need the asset pipeline. This is mostly relevant when exclusively using component-based JavaScript frameworks.

Should You Remove Your Old Pipe?

Since Webpacker is created to co-exist with your sprockets asset pipeline. The answer is not yet; there is no need to remove the asset pipeline especially for legacy applications that you want to start integrating Vue into. There may be a point where Ruby on Rails abandons sprockets, so it might be required to migrate assets to Webpacker in future versions. For new applications, we recommend starting with Webpacker for asset management.

Our advice is not to move towards Webpacker for your entire assets immediately, but allow Webpacker to manage the assets of your component while leaving the rest of your assets to assets pipeline. Webpacker is a major shift in how to manage assets, since legacy Rails applications use a lot of gems that assume use of the asset pipeline and sprockets, whereas Webpacker uses yarn where packages are retrieved from npmjs.​org. So it is important to consider the nature of your application and how to proceed with asset management. We’ll discuss how to use Webpacker using tools we have develop to make Vue integration seamless.

Getting Started with Webpacker

Webpacker is a wrapper around webpack and yarn. It makes it easy to use the JavaScript pre-processor and bundler ability of webpack to manage application-like JavaScript in Rails.

It co-exists with the asset pipeline, as the primary purpose for webpack is app-like JavaScript, not images, CSS, or even JavaScript Sprinkles (that all continues to live in app/assets). However, it is possible to use Webpacker for CSS, images, and fonts assets as well, in which case you may not even need the asset pipeline. This is mostly relevant when exclusively using component-based JavaScript frameworks.

Webpacker is essential for the approach we will follow throughout this book. It allows scaffolding of new Vue component and allows embedding of the component onto Rails views. The latest Webpacker ships with webpack 4.x and latest babel. This means we will enjoy free performance upgrade of webpack including the split chunk api and other benefits. You are encouraged to use Webpacker 4 in Ruby on Rails moving forward.

Installing Webpacker

Installing Webpacker is as simple as adding it to your Gemfile and running a couple of commands.
  1. 1.

    #At Gemfile

    gem 'webpacker'
     
  2. 2.
    Install webpacker and its dependencies:
    bundle install
    rails webpacker:install
     
  3. 3.

    Install Vue and its basic dependencies:

    rails webpacker:install:vue
     

Now that you are up and running with Webpacker, we’ll discuss the vueonrails gem and how to use it for Vue component scaffolding.

Scaffolding Vue on Rails Projects

Often times we need a simple and easy way to scaffold Vue component and its dependencies onto Ruby on Rails project. In this section, the vueonrails Ruby gem will be used to scaffold a Vue on Rails project with all its necessary configuration and dependencies we will need for a single component.
  1. 1.
    Add the vueonrails gem onto your Gemfile as well as the webpacker gem if it is not already there.
    gem 'vueonrails'
    gem 'webpacker'
     
  2. 2.
    Next, set up the project with an install generator:
    bundle install
    yarn install
    rails webpacker:install
    rails webpacker:install:vue
    rails vue:setup

    This runs rails webpacker:install and rails webpacker:install:vue and adds other dependencies like Vuex, Vue_component helpers, to your arsenal of tools.

     
  3. 3.

    Now generate a Vue component called home:

    rails generate vue home
     
  4. 4.

    Let us create a Rails view using the controller generator:

    rails generate controller pages home
     
  5. 5.
    Now, add the component pack tag along with the stylesheet pack tag to app/vies/layouts/application.html.erb:
    <%= javascript_pack_tag "home" %>
    <%= stylesheet_pack_tag "home" %>
     
  6. 6.

    You can run http://localhost:3000/pages/home to see your Vue component on a Rails page after starting the dev server:

    rails server
     
Using the Vue component scaffold, you can have a Vue component on your Rails project the quick and easy way. If you find these steps tedious, we made an application template that will get you up to speed in a single command. The template is available at https://vueonrails.com/vue and the command creates a new Vue on Rails-ready application.
rails new app -m https://vueonrails.com/vue -d postgresql

Rails First Approach: Putting Ruby on Rails before Vue

Consider the following simple example of a Yes/No answering robot. In this example, we will use only Ruby on Rails and its provided jQuery to build this example.

The Yes/No Answering Robot – Version 1

Follow these steps for our version 1 example:
  1. 1.
    Let’s create an empty Rails project:
    rails new v1_robot
    rails generate scaffold pages
    rails db:migrate
     
  2. 2.
    Next, copy and paste the following to app/views/pages/index.html.erb:
    <%= form_tag("/pages/search", method: "get", remote: true) do %>
      <%= label_tag(:q, "Please ask a yes or no question. For example: Is the sky blue?") %><br>
      <%= text_field_tag(:q) %>
      <%= submit_tag("Search") %>
    <% end %>
    <div id="result"></div>
     
  3. 3.
    Add the search action to the pages controller in app/controllers/pages_controller.rb
    def search
      @answer = ((rand(10)%2) == 1) ? "Yes" : "No"
    end
     
  4. 4.
    Use JS format to respond at app/views/pages/search.js.erb:
    $("result").text("<%= escape_javascript(@answer) %>");
     
  5. 5.
    Add the following JavaScript to app/assets/javascript/pages.js:
    $(document).ready(function() {
      $("#q").on( "input", function() {
        question()
      })
    })
    function question(){
      $("#result").val = 'Waiting for you to stop typing...'
      getAnswer()
    }
    function getAnswer(){
      if ($("#q").val().indexOf('?') === -1) {
        $("#result").text('Questions usually contain a question mark. :)')
        return
      }
      $("#result").text('Thinking...')
    }
     

So we’ve created a new Rails app that takes in a simple form that takes a question and randomly returns an answer of Yes or No. The answer is returned without re-rendering the page using the search endpoint with a js format. We add some JavaScript to add some client side validation for ensuring the question contains a question mark and inform the user that the robot is thinking about an answer while the answer is fetched from the backend. Next, we will evaluate this approach.

Evaluating the Rails-Only Approach

The patching of functionality via jQuery works. But can JavaScript be treated as a first-class asset than some working patchwork? As the app becomes bigger, the patchwork may lead to a “JavaScript soup” where JavaScript becomes more like a liability than a liberty of the web view.

Updating virtual DOM is cheaper than DOM. While jQuery is a DOM library, this approach did not leverage on the development of the virtual DOM. There is also a lack of data binding, reactivity, and other things including state management. These issues may become obvious as the answering robot becomes more complex.

Can a Vue-first approach solve some of the problems that Ruby on Rails and jQuery is limited to? Will Vue.js displace jQuery? What are some of the features that a Vue-first approach offer? We will evaluate a Vue-first approach in the next section.

Vue First Approach: Putting Vue before Ruby on Rails

In this section, we will be using a Vue-first approach with a single-page application and a Ruby on Rails API application:
  • It will be a single-page application where a web page is created so that it adds or subtracts dynamically through user interaction instead of rendering the same web page via the server. We will use vue-cli to generate the single-page application.

  • We will be reusing the backend from Rails-only approach for simplicity sake.

The Yes/No Answering Robot – Version 2

Follow these steps for our version 2 example:
  1. 1.

    Let’s install vue-cli:

    yarn install vue-cli
     
  2. 2.

    Now, let’s create a project called v2_robot:

    vue create v2_robot
     
  3. 3.
    Next, create the following src/robot/robot.vue:
    <template>
      <div>
        <label>Please ask a yes or no question.
          For example: Is the sky blue? </label>
        <input v-model="question">
        <button>Search</button>
        <p>{{ answer }}</p>
      </div>
    </template>
     
  4. 4.
    Create the following src/robot/robot.js. Axios is used as an HTTP client to communicate with the Ruby on Rails API backend.
      // import _ from 'lodash'
      import axios from 'axios'
      export default {
      data: function () {
        return {
          question: "",
          answer: ""
        }
      },
      watch: {
        question: function () {
          this.answer = 'Waiting for you to stop typing...'
          this.getAnswer()
         }
      },
      methods: {
         getAnswer: _.debounce(
           function () {
             if (this.question.indexOf('?') === -1) {
               this.answer = 'Questions usually contain a question mark. :)'
               return
             }
             this.answer = 'Thinking...'
             var vm = this
             axios.get('https://yesno.wtf/api')
               .then(function (response) {
                 vm.answer = _.capitalize(response.data.answer)
               })
               .catch(function (error) {
                 vm.answer = 'Error! Could not reach the API. ' + error
               })
           },
           500
         )
      }
    }
     
  5. 27.
    Search endpoint in a JSON format:
    def search
      answer = ((rand(10)%2) == 1) ? “Yes” : “No”
      render json: {answer: answer}
    end
     
  6. 28.

    Start the vue-cli server:

    vue serve
     
  7. 29.

    At a separate terminal, start your Ruby on Rails API server:

    rails server
     
  8. 30.

    Visit http://localhost:8080 to see your Vue app.

     

Evaluating the Vue-First Approach

There are both favorable and unfavorable aspects to the Vue-first approach. Let’s consider both the pros and the cons.

Pros:
  • Having an unobtrusive reactivity by leveraging on an asynchronous virtual DOM update

  • Having clear separation of client and server responsibilities. Useful for a big team with a sizable budget

  • Making it desirable for teams with dedicated frontend and backend developers

  • Having more room to build a complex and dedicated user interface

  • Having a simple and clean syntax. Not reinventing the wheel but reusing the HTML syntax

  • Allowing component-based architecture for code reusing

  • Being extremely progressive in nature. Allow incremental improvement of the user interface

  • Making it useful for existing applications that require or already expose an API

Cons :
  • Juggling with two project directories (Vue-cli and Rails) can be a pain.

  • Abandoning Ruby on Rails helpers. For instance, form helpers becoming obsolete.

  • Abandoning Ruby on Rails router becomes obsolete in favor of Vue Router.

  • Lacking a clear and supported interface for interacting with Ruby on Rails.

  • Having a component-based structure is not always straightforward and may add complexity to the application.

This approach will generate a more dynamic answering robot since Vue.js is reactive; the web page does not require a web page refresh.

Moreover, there is an increase in supporting libraries from two ecosystems. This may be a double-edged sword as more tools do not mean getting more work done.

This approach increases the complexity by having to juggle two project structures that are bind by a loosely coupled JSON API. There is also a need to relearn routing in a Vue.js application if you are a Ruby on Rails developer.

All in all, the rabbit hole of diving into Vue.js with a single-page application making Ruby on Rails a backend only solution is too risky.

Is Vue-first with Rails API the best way to build a web application? Could there be an easier way to integrate Vue.js without going to juggling two projects structures for one web application product? Let’s find out in the next section.

A Good Balance: Vue as a First-Class Citizen of Rails

We want to achieve the best of both worlds and do what works. In this section we’ll use an approach that uses Webpacker and streamlines Vue integration.

The Yes/No Answering Robot – Version 3

If you are not satisfied with either the Vue-first or Rails-only approach, we share the same sentiment.

In this version of the Yes/No answer robot, we will use Rails’ Webpacker to deliver a Vue-first class and Rails-first approach to building a web application. The idea is to follow Ruby on Rails conventions and the traditional MVC pattern (2-1a) and take advantage of Vue for components of the application that requires interactive elements (2-1b).
../images/465247_1_En_2_Chapter/465247_1_En_2_Fig1_HTML.png
Figure 2-1

Traditional MVC pattern (left) and MVC with components in the view layer (right)

Vue on Rails project shouldn’t be about conquering every web page with a single-page application. It should start with conquering each component and trying to reuse them on the relevant web page.

Webpacker is an efficient way to divide a web page into important components and let Vue do the heavy lifting for a more complex interface.

Webpacker also provides a clean and clear interface for Vue.js to interact with Ruby on Rails, and it ships with some basic configuration of Vue Webpacker configuration.

Creating Version 3

Let’s get started in making version 3 of the Yes/No answering robot.
  1. 1.

    Initialize a new rails app with the Vue webpack integration.

    rails new v3_robot --webpack=vue
     
  2. 2.
    Next, at your terminal, run the following:
    rails g scaffold pages
    rails db:migrate
     
  3. 3.
    Then, create the following app/javascript/robot.vue to the same JavaScript code in the previous section. Change import App from '../app.vue' to import App from '../robot.vue':
    //app/javascript/search.js
    import Vue from 'vue'
    import App from '../robot.vue' #change this
    document.addEventListener('DOMContentLoaded', () => {
      const el = document.body.appendChild(document.createElement('search'))
      const app = new Vue({
        el,
        render: h => h(App)
      })
      console.log(app)
    })
     
  4. 4.
    Next, at your app/views/pages/index.html.erb, replace the entire page with the following code:
    <!-- app/views/pages/index.html.erb -->
    <%= javascript_pack_tag "robot" %>
     
  5. 5.

    At your terminal, run this

    rails server
     
  6. 6.

    Please visit http://localhost:3000/pages to see the robot.

     

Evaluating the Vue as a First-Class Citizen of Rails Approach

Like other approaches, this one also has its pros and cons, though as we’ll see it is more favorable overall.

Pros
  • Having access to both Vue.js and Ruby on Rails ecosystem in your toolbelt

  • Enjoying the clean interface of webpacker and separation of concern of frontend component and backend API

  • Enjoying the best of Vue – True unobtrusive reactivity and asynchronous virtual DOM update

  • Enjoying component-based architecture on top of the model view-controller framework

  • Retaining the Ruby on Rails helpers for programmers’ happiness

  • Having a simpler architecture than a single-page application architecture

  • Having the ease of upgrading and maintaining on both Vue and Rails

Cons
  • Having a monolithic application may not be suitable for a big development team.

  • Having a Vue component delivered through Webpacker may result in tight coupling when compared to a single-page application with total separation of frontend/backend responsibility.

  • Having too many Vue components may complicate the Rails’ view.

This is a completely different approach where we do not do a surgical procedure on Ruby on Rails or Vue to make them work together. Rather, through Webpacker, we deliver the best of Vue on top of the Ruby on Rails model view-controller architecture. This architecture allows us to follow traditional Rails conventions but allows us to take advantage of the simplicity of Vue and add in components when plain old JavaScript may be too bloated for what you are trying to accomplish.

The caveat is that we assume a small team of 2-4 developers for a small- to medium-sized web application. But this approach may not be desirable for a smaller team or a single programmer where resources are limited.

Reusability: A Powerful Proposition of the Vue Component

Most web pages do not need a complex UI. Not all pages will have a full-fledged calendar or text editor, to begin with. But when you need a complex interface, a component-based architecture will help. A component-based architecture diversifies the Rails views towards modern user interface with the support of Rails API.

Each component packs all the Vue.js goodness into a manageable object. And each component is a Vue instance. It allows reusable code by extending HTML code. Furthermore, Vue component allows you to enjoy access to a Vue’s lifecycle and reactive nature of Vue.js and, above all, have all these in a progressive and reusable manner.

All in all, Vue component offers a systematic way to organize complex user interface into a component object. Programmers can then use this approach to conquer complex page that requires modern UI by dividing them into multiple components and managing them separately without needing to build a single-page application.

Reactivity: Data-Binding and Virtual DOM of Vue

Since each Vue component packs the full features of Vue, it inherits the reactivity system, data binding, and virtual DOM management of Vue.

Reactivity system is one of the reasons why Vue component can turn a boring and static web page into life. It gives the responsiveness and fluidity of a modern web page. Vue brings in some flavor to sections of a Ruby on Rails application that follows conventional routing. It allows us to make an application more interactive and easy to use than your standard resources that you might see from scaffolding a resource in a Rails app.

Wrap-up and the Next Step

We’ve discussed how to approach a Vue on Rails application from an architecture perspective by demonstrating a few examples. We determined that using a Vue as a first-class citizen approach that uses Webpacker is an ideal scenario and will dive deeper into this approach throughout the book.

There are other features of Vue like validation, internationalization, plugin system, directives, state management, and more. You can also see a list of all the features supported by Vue on Rails at the end of this book.

In the next section, we will examine a way to quickly scaffold Vue component onto Ruby on Rails project and other essential parts of a modern web application.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.163.58