MAKE SIMPLE RAILS APP WITH ANGULARJS – PART I

I.INTRODUCE ABOUT ANGULARJS

Nếu bạn là developer đã từng quen làm việc với Ruby on Rails hoặc 1 số web framework tương tự khác đều sẽ dễ dàng nhận thấy điểm chung trong thiết kế của chúng đó là sau mỗi tác vụ update hay delete ở server mọi thứ đều sẽ được redirect lại hay nói cách khác page ở client bạn đang tương tác sẽ được reload lại để lấy về các bản ghi mới. Điều đó đôi khi là không cần thiết và lãng phí tài nguyên khi bạn chỉ thay đổi 1 record nhưng phải load lại đến cả nghìn record trong database chưa kể đến layout, css, ...Ở 1 số page cần thiết, chúng ta có thể dễ dàng thay đổi điều đó bằng cách sử dụng các Ajax request, nhưng một cách đồng bộ và hệ thống hơn, AngularJs sinh ra để làm việc đó giúp bạn với live-edit, live-update.

Tận dụng một cách triệt để lợi ích mà AngularJS đem lại, developer có thể tách riêng rẽ client-side và server-side của web app và tiến hành phát triển cả 2 thứ đó song song với nhau cũng như là sử dụng lại 1 cách hiệu quả.Sau đây là một số điểm mạnh của AngularJS:

  • Two Way Data-Binding Bạn có thể thao tác với model ở bất cứ đâu trong application nhờ vào data-binding và cũng không cần phải lo lắng về traversing hay event handler, giờ đây DOM luôn luôn được up-to-date với sự thay đổi trên database hay form input sau khi đã binding với nhau.

  • Templates Nếu đã từng làm việc với thư viện Handlerbars chắc bạn sẽ không còn xa lạ gì với tính năng này, thay vì việc code HTML truyền thống, AngularJS cho phép xây dựng cấu trúc để model được hiển thị ra trên view. Điều đó có nghĩa input của AngularJS sẽ là các DOM thay vì string value của model.HTML template có thể được lưu vào variable và sử dụng lại nhiều lần.

  • MVC AngularJS cũng được thiết kế theo mô hình MVC với đầy đủ 3 thành phần:

  • ViewModel($scope): 1 object chứa thông tin của các records và đôi khi là các method sẽ tương tác với 1 view cụ thể nào đó, ví dụ như $scope sẽ có thể là User.all trong view users/index

  • View: Sử dụng tính năng template và config $routeProvider, AngularJS thậm chí có thể thay thể sever trong việc điều hướng các request và sử dụng view HTML của riêng mình.

  • Controller: chịu trách nhiệm khởi tạo ViewModel và khai báo các method sẽ tương tác với server-side

II.DEMO

Hãy cùng làm thử 1 sample app nho nhỏ để xem AngularJs đem lại những lợi thế gì so với 1 Rails app truyền thống

  • Khởi tạo 1 rails app đơn giản:
$rails new task_angular
$cd task_angular
  • Tạo 1 model có tên là Task gồm các trường cơ bản:
rails g model task title:string content:string
  • Tạo database và migrate:
$rake db:create
$rake db:migrate
  • Tư tưởng chủ đạo của AngularJS chính là server-side đóng vai trò như là 1 api server.

    config/routes.rb

    Rails.application.routes.draw do
        namespace :api, defaults: {format: :json} do //set format mặc định của các request là `json`
            namespace :v1 do
                resources :tasks
            end
        end
        root to: "home#index" // controller đơn giản để hiển thị homepage
    end
  • Trong tasks_controller.rb khai báo các action restful cơ bản nhưng chỉ trả ra json status
    module Api
        module V1
            class TasksController < ApplicationController
                skip_before_filter :verify_authenticity_token
                before_filter :find_model, except: [:index, :create]
                respond_to :json

                def index
                    respond_with Task.all
                end

                def create
                    @task = Task.new task_params
                    if @task.save
                        respond_to do |format|
                            format.json{render json: @task}
                        end
                    end
                end

                def show
                    respond_with @task
                end

                def update
                    if @task.update task_params
                        respond_to do |format|
                            format.json{render json: @task}
                        end
                    end
                end

                def destroy
                    respond_with Task.destroy params[:id]
                end

                private
                def find_model
                    @task = Task.find(params[:id]) if params[:id]
                end

                def task_params
                    params.permit :title, :content
                end
            end
        end
    end
  • Khởi tạo angular trong app/assets/javascripts/main.js
angular.module('demoApp', ['ngResource']);
  • Khởi tạo 2 method là createdelete trong app/assets/javascripts/angular/controlers/tasks.js đường dẫn mặc định sẽ được dẫn đến /api/v1/tasks/taskId và model sẽ là Task
    angular.module('demoApp').factory('Task', function($resource){
        return $resource('/api/v1/tasks/:taskId');
});
    angular.module('demoApp').controller('TasksCtrl', function($scope, Task){
        $scope.tasks = Task.query();

        $scope.create = function(title, content){
            Task.save({title: title, content: content}, function(task) {
                $scope.tasks.push(task);
            });
        };

        $scope.delete = function(index) {
            Task.delete({taskId:$scope.tasks[index].id}, function() {
                $scope.tasks.splice(index, 1);
            });
        };
    });
  • Khởi tạo app/views/layouts/application.html.erb
<!DOCTYPE html>
    <html class="no-js" ng-app="demoApp"><!--khai báo thẻ html thuộc quyền xử lí của demoApp-->
        <head>
            <meta charset="utf-8">
            <title>TaskAngular</title>
            <script src="https://code.jquery.com/jquery-2.1.1.js"></script>
            <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
            <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
        </head>
        <body>
            <div class="container" >
                <%= yield %>
                <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js"></script>
                <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular-resource.min.js"></script>
                <%= javascript_include_tag 'application'%>
            </div>
        </body>
    </html>

app/views/home/index.html.haml

    <div class="row" ng-controller="TasksCtrl">
        <div class="span5">
            <form ng-submit="create(title, body)" class='well'>
                <h3>Tasks</h3>
                <fieldset>
                    <input ng-model='title' type="text" class="input-xlarge" placeholder="Title..." required>
                    <br/>
                    <textarea rows='10' ng-model="content" type="text" class="input-xlarge" placeholder="Text..." required></textarea>
                    <br/>
                    <button type="submit" class="btn">Submit</button>
                </fieldset>
            </form>
        </div>

        <div class="span5 offset2">
            <div class="well" ng-repeat="task in tasks">
                <a href="" title="Delete" ng-click="delete($index)" class="pull-right">Delete</a>
                <h3>{{task.title}}</h3>
                <p>{{task.content}}</p>
            </div>
        </div>
    <div>
  • Chạy localhost:3000 và cùng xem thành quả. Bây giờ chúng ta có thể tạo ra 1 task mới, được tự động thêm vào list hay xóa đi mà không cần phải reload lại trang web.

    0e4723d14bae2845c5b8cf0f524ff1a1

    Các bạn có thể tham khảo source code cho part I tại đây


All Rights Reserved