Building Mobile Applications With Rails and Ionic

本文介绍如何在rails上面开发ionic.

Rails 关键 Gem 介绍

grape

An opinionated micro-framework for creating REST-like APIs in Ruby

  1. 非常轻量,可以脱离Rails,直接运行在Rack服务器之上,速度非常快;
  2. 完全符合REST风格;
  3. 大量DSL简化API的编写;
  4. 提供简单的版本控制;
  5. 文件目录结构:
1
2
3
4
5
6
7
8
9
10
11
├── services
|   ├── api
|   |   ├── entities
|   |   ├── helpers
|   |   |   ├── api_strong_parameters.rb
|   |   |   ├── authorization_helper.rb
|   |   |   └── response_helper.rb
|   |   └── v1
|   |       ├── model.rb
|   |       └── ...
|   ├── api.rb
6. 添加配置至application.rb
1
2
config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb')
config.autoload_paths += Dir["#{config.root}/app/services/*"]

grape-entity

Entities - a simple Facade to use with your models and API - extracted from Grape.

1. 自定义放回的内容
2. 嵌套返回数据
3. ...

grape-swagger-rails

Integration swagger to grape in rails

1. API在线测试工具

rack-cors

Rack Middleware for handling Cross-Origin Resource Sharing (CORS), which makes cross-origin AJAX possible.

1. 配置服务端允许跨域请求
2. 添加配置至application.rb,以允许所有请求的跨域操作
1
2
3
4
5
6
7
8
9
config.middleware.insert_before 0, "Rack::Cors", :debug => true,:logger => (-> { Rails.logger }) do
    allow do
        origins '*'
        resource '*',
        :headers => :any,
        :methods => [:get, :post, :delete, :put, :options, :head],
        :max_age => 0
    end
end

jpush

极光推送官方支持的 Ruby 版本服务器端 SDK

1. 通过配置app_key 和 app_secret 即可发推送通知
2. demo 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class PushNotifier
  class << self
    def client
      return @client if @clien
      jpush_configs = Rails.application.secrets['jpush']
      @client = JPush::JPushClient.new *jpush_configs.values_at('app_key', 'app_secret')
    end
    def push(message, receiver_credential_ids, extras = {})
      # See how to define audience for pushing message, visit:
      # https://github.com/jpush/jpush-api-ruby-client/blob/master/example/push_example.rb
      receiver_credential_ids = [*receiver_credential_ids]
      payload = JPush::PushPayload.build(
        platform: JPush::Platform.all,
        audience: JPush::Audience.build(:_alias=> receiver_credential_ids),
        notification: JPush::Notification.build(
          alert: message,
          ios: JPush::IOSNotification.build(
            alert: message,
            badge: "+1",
            sound: "happy",
            extras: extras
          ),
          android: JPush::AndroidNotification.build(
            alert: message,
            builder_id: 1,
            extras: extras
          )
        ),
        message: JPush::Message.build(
          msg_content: "message content test",
          title: "schoolmatch",
          content_type: "message content type test",
          extras: extras
        ),
        options:JPush::Options.build(
          sendno: 1,
          apns_production: Rails.env.production?
        )
      )
      result = client.sendPush(payload)
      Rails.logger.debug "Pushed message: #{result}"
      result
    end
    def debug?
      %w(development test staging).include? Rails.env
    end
  end
end
# usage: PushNotifier.push('test', 1)
3. 注意`badge: "+1"`配置,该配置是jpush通过维护用户未读消息数,每次推送时,都会自动在当前消息数上做加1操作

stripe

关于stripe的集成,清参考Marting大神的 blog

china_sms

中国各个短信平台 Ruby 接口,现支持云片网、推立方、亿美软通、短信宝、畅友网络

1. 在这里我们使用[云片网](yunpian.com)进行短信验证
2. 添加secret_key
3. 在云片网后台添加服务器IP白名单,签名,模板,等待审核
4. 审核通过,可在Rails Console里面发送短信
  demo code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ChinaSMS.use :yunpian, password: Rails.application.secrets.china_sms["password"]
ChinaSMS.class_eval do
  def self.debug
    Rails.env.development? || Rails.env.test?
  end
  def self.send_to(phone, message, debug = false)
    if debug || self.debug
      Rails.logger.debug(message)
    else
      # use sidekiq to send sms asynchronously
      delay.to(phone, message)
    end
  end
end
# "【留学助手】#{3721}(短信验证码,有效期3分钟,请尽快使用)" 该模板必须审核通过
# usage: ChinaSMS.send_to 15820700248, "【留学助手】#{3721}(短信验证码,有效期3分钟,请尽快使用)"
5.在这里,为了配合验证码验证需求,需要在相应model上添加`verification_code`、`verification_expire_at`等字段

Iionic

Ionic简单介绍

  1. H5 navative app(HTML,CSS,Javascript)
  2. Cordova/PhoneGap + AngularJs + AngularJs

    命令行工具

1
2
3
4
5
  alias 'ionic-serve'='ionic serve'
  alias 'ionic-build-ios'='ionic build ios'
  alias 'ionic-run-ios'='ionic run ios'
  alias 'ionic-emulate-ios'='ionic emulate ios --livereload'
  alias 'ionic-update-ios'='ionic platform update ios'

构建工具

图形化 ionic APP 构建工具 Ionic Creator,只需要拖拽就能创建基于 ionic 的 APP了

目录结构

简单介绍angular的目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
├── www
|   ├── js
|   |   ├── app.js
|   |   ├── controllers.js
|   |   ├── directives.js
|   |   ├── helper.js
|   |   ├── routes.js
|   |   ├── services.js
|   |   └── translations.js
|   ├── css
|   ├── templates
|   ├── img
|   ├── lib
|   └── index.html

IOS开发证书配置简单介绍

  1. 创建App Id
  2. 创建 Apns证书
  3. 创建 Provisioning Profile 证书
  4. 配置Xcode 注意:有时候Provisioning Profile证书在xcode没有生效,重启xcode即可 图文链接清参考:
  5. jpush 官网
  6. fir 官网

调试技巧

  1. Debug using Chrome AngularJS Batarang
  2. Debug Using Safari
  3. Using Xcode
  4. Debug with Ionic CLI
1
2
3
4
5
6
7
8
9
10
11
alias 'ionic-emulate'='ionic emulate ios -l -c -s'
ionic  [run|emulate] <platform> [options]
    [--livereload|-l] .... Live Reload app dev files from the device
    [--consolelogs|-c] ... Print app console logs to Ionic CLI
    [--serverlogs|-s] .... Print dev server logs to Ionic CLI

1. restart or r to restart the client app from the root
2. goto or g and a url to have the app navigate to the given url
3. consolelogs or c to enable/disable console log output
4. serverlogs or s to enable/disable server log output
5. quit or q to shutdown the server and exit

性能优化

  1. 整合 Crosswalk 至 Cordova(一个Web运行环境),替换自带的 Webview。 具体做法,可以参考 ionic 上的链接: Crosswalk Build
  2. 关闭页面切换动画,即 animation=“no-animation”
  3. 读取模板的时候,显示“加载中”圈圈,避免出现无响应的错觉
  4. 使用 Pasvaz/bindonce,避免 Angular.js 对静态内容绑定所带来的性能消耗

Ionic能做什么?

多语言支持

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
translations = {
  en: {
    students: 'Students',
  },
  zh: {
    students: '同学',
  }
};
app.config(function ($translateProvider) {
  //Get system language
  var systemLang = navigator.language || navigator.userLanguage;
  for(lang in translations){
    $translateProvider.translations(lang, translations[lang]);
  }
  //Set app language
  var appLang = helper.matchLanguageString(systemLang);
  $translateProvider.preferredLanguage(appLang);
});

消息推送

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
angular.module('xx.services', [])
  .factory('Push', function() {
    var push;
    return {
      setAlias: function(alias) {
        if (push) {
          console.log('jpush: set alias', alias);
          plugins.jPushPlugin.setAlias(alias);
        }
      },
      init: function(notificationCallback) {
        console.log('jpush: start init-----------------------');
        push = window.plugins && window.plugins.jPushPlugin;
        if (push) {
          console.log('jpush: init');
          plugins.jPushPlugin.init();
          plugins.jPushPlugin.setDebugMode(true);
          plugins.jPushPlugin.openNotificationInAndroidCallback = notificationCallback;
          plugins.jPushPlugin.receiveNotificationIniOSCallback = notificationCallback;
          plugins.jPushPlugin.receiveMessageIniOSCallback = notificationCallback;
        }
      }
    };
  })

Push.init(notificationCallback);
var notificationCallback = function(data){
    var notification = angular.fromJson(data);
    //app 是否处于正在运行状
    var isActive = notification.notification;
    // here add your code
}

ngcordova Plugin

调用手机摄像头 IOS指纹识别 OAuth 获取地理位置

如何与Rails结合

  • Rails 负责提供REST API
  • Ionic 通过ng-resource调用REST API

测试与发布

  • Android 打包
  • iOS 打包
  • 发布测试版本 fir.im
  • 生成截图 screenshots
  • 提交到 app store

什么时候用Ionic

  • 用Ionic开发的优点和缺点

    • 优点: 一次开发,多个平台,开发效率高
    • 缺点: 1.对开发人员的要求很高,如果需要编译成native app需要开发人员了解 web、ios、andriod 三种开发技术 2.性能问题 3.不支持较低Android版本(4.1)
  • 哪些应用适合用Ionic来开发:

    • 不属于游戏之类的APP类型;
    • 想低成本、快速迭代地开发 Android、iOS 平台上的应用;
    • 目标终端的设备性能不算低;
    • 国内例子
    • 国外例子

Comments