日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Rails下cloud datastore的使用

發布時間:2025/3/15 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Rails下cloud datastore的使用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?


?Rails下cloud datastore的使用

背景

部門有一個項目要用Ruby做 WebAPI,DB使用關系型數據庫Cloud Sql和非關系型數據庫Cloud Datastore 。

還不了解Ruby On Rails和CloudDatastore的請參考下面的鏈接。

http://guides.ruby-china.org/

https://thinkit.co.jp/story/2015/02/05/5594

?

1、 Windows下開發環境構建

1.1、構建Ruby On Rails 開發環境

① Ruby安裝

http://www.runoob.com/ruby/ruby-installation-windows.html

② Rail安裝

從CMD提示窗口輸入指令:gem install rails 開始安裝rails。

注意:在中國直接安裝會提示錯誤,因為gem默認的安裝源https://rubygems.org在國內不能訪問,還好先輩們早已為我們新搭建了一個gem安裝源http://gems.ruby-china.org。下面是切換安裝源的具體步驟,gem安裝源切換之后,Rails安裝就可以順利進行了。

第一步:刪除默認安裝源

CMD提示窗中輸入”gem sources -remove https://rubygems.org/”,回車換行。

第二步:添加新的安裝源

CMD提示窗輸入“gem sources -add? http://gems.ruby-china.org/”,回車換行。

③ ruby的IDE Ruby Mine安裝

http://qiita.com/HALU5071/items/6d6a39e44865d8d04de8

1.2、搭建開發用Cloud Datastore 數據庫

① 安裝Google Cloud SDK

http://www.apps-gcp.com/google-cloud-sdk-install

② 安裝cloud-datastore-emulator

CMD提示窗中輸入“gcloud components install cloud-datastore-emulator”,回車換行。

③ 創建一個開發用的DB:dev_datastore

CMD提示窗中輸入“cloud_datastore_emulator create db/dev_datastore”,回車換行。

前提條件:CMD當前運行目錄下要先創建一個db的文件夾。

創建好的DB文件結構圖如下:

?

2、 WEB API工程創建

在CMD提示窗中輸入“rails new my-first-api --api”,回車換行。

創建好的API工程結構見下圖,rails執行結果見附錄1。

フォルダ構造

 

 

説明

Gemfile

 

gemの依存関係を指定できるファイル

README.rdoc

 

説明書

Rakefile

ターミナルから実行可能なタスク

 

config.ru

 

Rackの設定

app/

 

アプリケーションを格納するディレクトリ

主要なプログラムはこの配下に格納

 

controllers/

コントローラを格納するディレクトリ

 

controllers/application_controller.rb

アプリケーションで共通のコントローラ

 

models/

モデルを格納するディレクトリ

config/

 

プロジェクトの設定ファイルを格納するディレクトリ

config/environments/

 

環境単位の設定ファイルを格納するディレクトリ

config/initializers/

 

初期化ファイルを格納するディレクトリ

config/locales/

 

辭書ファイルを格納するディレクトリ

db/

 

データベースの設定ファイルを格納するディレクトリ

doc/

 

ドキュメントを格納するディレクトリ

lib/

 

複數のアプリケーション間で共有するライブラリを格納するディレクトリ

 

tasks/

自分で生成したRakefileを格納するディレクトリ

log/

 

ログファイルが格納されるディレクトリ。ログファイルはアプリケーションと環境ごとに作成される

public/

 

Web上に公開するファイルを格納するディレクトリ

tmp/

 

キャッシュなど、一時的なファイルを格納されるディレクトリ

test/

 

アプリケーションのテストに使うファイルを格納するディレクトリ

vendor/

 

ライブラリや他のアプリケーションで共有するような外部ライブラリを格納するディレクトリ

?

在附錄1的最后我們看到,bundle install 并沒有成功。原因是項目的gem安裝源出了問題。打開Gemfile把第一行的source 'https://rubygems.org'替換成source 'http://gems.ruby-china.org'。然后在CMD里重新執行bundle install命令,這樣項目需要的gem就能成功安裝。

?

3、 新建cloud Datastore 的dataset對象

① Gem安裝

在Gemfile 中追加

gem 'google-cloud-datastore'

cmd里重新執行bundle install命令。

② 配置文件

在config/initializers/目錄下新建cloud_datastore.rb文件,文件內容如下圖所示。

從圖中我們可以看到cloud datastore 配置了三種環境下創建daset的參數,這些參數我們都放在了config/database.yml里。下面是database.yml里開發環境的配置信息,datastore 安裝的主機和datastore的數據庫名,這樣我們就可以使用datastore了。

development:
????????host: 'localhost:8180'
????????project: ' dev_datastore '

?

?

cloud_datastore.rb

?

4、 非關系型數據庫 中ActiveModel 的使用

如果我們想要cloud datastore和關系型數據庫一樣,可以方便快捷使用model(ActiveModel),怎么辦?下面就是你想要的答案。

① 追加文件

在config/initializers/目錄下新建active_model_cloud_datastore.rb文件。

文件內容參照附錄2。

② model Class寫法

require_relative "../../config/initializers/active_model_cloud_datastore" class Customer
include ActiveModelCloudDatastore
attr_accessor :customer_code, :customer_name

def attributes
%w(code customer_name)# 注意多個字段之間是半角空格來區分的
end end

這樣我們就可以使用activeModel很多功能,

#檢索所有數據

@customers = Customer.all

#保存一條新的數據

@customer = Customer.new

@customer.save

這里就不做詳細說明,具體參照附錄2里的各種方法。

5、 spec測試

  • 1.? ?
  • 2.? ?
  • 3.? ?
  • 4.? ?
  • 5.? ?
  • ① 測試環境安裝

    在Gemfile中追加下面的gem。

    group :development, :test do
    # Test
    gem 'rspec-rails', '~> 3.0'
    gem 'rails-controller-testing'
    end

    然后在cmd工程目錄my-first-api下執行bundle install,安裝追加的gem。

    ② 測試環境初期化

    在cmd工程目錄my-first-api下執行

    bundle exec rails generate rspec:install

    會生成下面的文件

    create? .rspec create? spec create? spec/spec_helper.rb create? spec/rails_helper.rb

    ③ controller測試

    參考下面鏈接

    http://qiita.com/shizuma/items/84e07e558abd6593df15

    http://blog.naichilab.com/entry/2016/01/19/011514

    ④ model測試

    參考下面的測試思路。

    http://qiita.com/shizuma/items/c7b8d7b91e8f325f8ad9

    ⑤ Mock使用

    參考下面鏈接

    http://qiita.com/jnchito/items/640f17e124ab263a54dd

    6、 測試覆蓋率報告

    ① ?環境搭建

    在Gemfile中追加下面的gem。

    group :development, :test do
    gem 'simplecov'
    end

    然后在cmd工程目錄my-first-api下執行bundle install,安裝追加的gem。

    ② spec_helper.rb修改

    在spec_helper.rb頭部插入下面的語句,覆蓋率測試中要過濾掉spec下的測試代碼。

    require 'simplecov'
    SimpleCov.start do
    add_filter "/spec/ "
    end

    ③ 查看報告

    在cmd工程目錄my-first-api下,再次執行rspec spec命令,覆蓋率報告就會自動生成再demo/coverage下,用google chrome瀏覽器打開index.html,就可以看到詳細的信息。下面是一個覆蓋率報告的截圖。

    7、 結束語

    上面我們講述的是Ruby下怎么使用cloud datastore的開發和測試,在Google Cloud Platform上怎么部署產品還有待下一步探索。期間遇到的各種技術問題難題,為了解決這些問題,調查的網站以日語和英語為主,總結的時候也使用了很多日語網站,由于時間有限,沒能一一翻譯過來,給不懂日語的朋友帶來不少困難表示歉意。


    附錄1

    API工程創建文件list

    create

    create? README.md

    create? Rakefile

    create? config.ru

    create? .gitignore

    create? Gemfile

    create? app

    create? app/assets/config/manifest.js

    create? app/assets/javascripts/application.js

    create? app/assets/javascripts/cable.js

    create? app/assets/stylesheets/application.css

    create? app/channels/application_cable/channel.rb

    create? app/channels/application_cable/connection.rb

    create? app/controllers/application_controller.rb

    create? app/helpers/application_helper.rb

    create? app/jobs/application_job.rb

    create? app/mailers/application_mailer.rb

    create? app/models/application_record.rb

    create? app/views/layouts/application.html.erb

    create? app/views/layouts/mailer.html.erb

    create? app/views/layouts/mailer.text.erb

    create? app/assets/images/.keep

    create? app/assets/javascripts/channels

    create? app/assets/javascripts/channels/.keep

    create? app/controllers/concerns/.keep

    create? app/models/concerns/.keep

    create? bin

    create? bin/bundle

    create? bin/rails

    create? bin/rake

    create? bin/setup

    create? bin/update

    create? config

    create? config/routes.rb

    create? config/application.rb

    create? config/environment.rb

    create? config/secrets.yml

    create? config/cable.yml

    create? config/puma.rb

    create? config/environments

    create? config/environments/development.rb

    create? config/environments/production.rb

    create? config/environments/test.rb

    create? config/initializers

    create? config/initializers/application_controller_renderer.rb

    create? config/initializers/assets.rb

    create? config/initializers/backtrace_silencers.rb

    create? config/initializers/cookies_serializer.rb

    create? config/initializers/cors.rb

    create? config/initializers/filter_parameter_logging.rb

    create? config/initializers/inflections.rb

    create? config/initializers/mime_types.rb

    create? config/initializers/new_framework_defaults.rb

    create? config/initializers/session_store.rb

    create? config/initializers/wrap_parameters.rb

    create? config/locales

    create? config/locales/en.yml

    create? config/boot.rb

    create? config/database.yml

    create? db

    create? db/seeds.rb

    create? lib

    create? lib/tasks

    create? lib/tasks/.keep

    create? lib/assets

    create? lib/assets/.keep

    create? log

    create? log/.keep

    create? public

    create? public/404.html

    create? public/422.html

    create? public/500.html

    create? public/apple-touch-icon-precomposed.png

    create? public/apple-touch-icon.png

    create? public/favicon.ico

    create? public/robots.txt

    create? test/fixtures

    create? test/fixtures/.keep

    create? test/fixtures/files

    create? test/fixtures/files/.keep

    create? test/controllers

    create? test/controllers/.keep

    create? test/mailers

    create? test/mailers/.keep

    create? test/models

    create? test/models/.keep

    create? test/helpers

    create? test/helpers/.keep

    create? test/integration

    create? test/integration/.keep

    create? test/test_helper.rb

    create? tmp

    create? tmp/.keep

    create? tmp/cache

    create? tmp/cache/assets

    create? vendor/assets/stylesheets

    create? vendor/assets/stylesheets/.keep

    remove? app/assets

    remove? lib/assets

    remove? tmp/cache/assets

    remove? vendor/assets

    remove? app/helpers

    remove? test/helpers

    remove? app/views/layouts/application.html.erb

    remove? public/404.html

    remove? public/422.html

    remove? public/500.html

    remove? public/apple-touch-icon-precomposed.png

    remove? public/apple-touch-icon.png

    remove? public/favicon.ico

    remove? app/assets/javascripts

    remove? config/initializers/assets.rb

    remove? config/initializers/session_store.rb

    remove? config/initializers/cookies_serializer.rb

    Fetching gem metadata from https://rubygems.org/..........

    Fetching version metadata from https://rubygems.org/..

    Fetching dependency metadata from https://rubygems.org/.

    Resolving dependencies...

    Using rake 12.0.0

    Using i18n 0.7.0

    Using minitest 5.10.1

    Using thread_safe 0.3.5

    Using builder 3.2.2

    Using erubis 2.7.0

    Using mini_portile2 2.1.0

    Using rack 2.0.1

    Using nio4r 1.2.1

    Using websocket-extensions 0.1.2

    Using mime-types-data 3.2016.0521

    Using arel 7.1.4

    Using bundler 1.13.6

    Using method_source 0.8.2

    Using puma 3.6.2

    Using thor 0.19.4

    Using sqlite3 1.3.12

    Gem::RemoteFetcher::FetchError: SSL_connect returned=1 errno=0 state=SSLv3 read

    server certificate B: certificate verify failed

    (https://rubygems.org/gems/concurrent-ruby-1.0.4.gem)

    An error occurred while installing concurrent-ruby (1.0.4), and Bundler cannot

    continue.

    Make sure that `gem install concurrent-ruby -v '1.0.4'` succeeds before

    bundling.


    附錄2

    active_model_cloud_datastore.rb文件內容:

    # frozen_string_literal: true

    require_relative 'cloud_datastore'
    require 'active_model'
    require 'active_support'


    # Integrates ActiveModel with the Google::Cloud::Datastore
    module ActiveModelCloudDatastore
    extend ActiveSupport::Concern
    include ActiveModel::Model
    include ActiveModel::Dirty
    include ActiveModel::Validations
    include ActiveModel::Validations::Callbacks

    included do
    private_class_method :query_options, :query_sort, :query_property_filter
    define_model_callbacks :save, :update, :destroy
    attr_accessor :id
    end

    def
    attributes
    []
    end

    # Used by ActiveModel for determining polymorphic routing.
    def persisted?
    id.present?
    end

    # Resets the ActiveModel::Dirty tracked changes
    def reload!
    clear_changes_information
    end

    # Updates attribute values on the ActiveModel::Model object with the provided params.
    # Example, such as submitted form params.
    #
    # @param [Hash] params
    def update_model_attributes(params)
    params.each do |name, value|
    send "#{name}=", value if respond_to? "#{name}="
    end
    end

    # Builds the Cloud Datastore entity with attributes from the Model object.
    #
    # @return [Entity] the updated Google::Cloud::Datastore::Entity
    def build_entity(parent = nil)
    entity = CloudDatastore.dataset.entity(self.class.name, id)
    entity.key.parent = parent if parent
    attributes.each do |attr|
    entity[attr] = instance_variable_get("@#{attr}")
    end
    entity
    end

    def
    save(parent = nil)
    run_callbacks :save do
    if
    valid?
    entity = build_entity(parent)
    success = self.class.retry_on_exception? { CloudDatastore.dataset.save(entity) }
    if success
    self.id = entity.key.id
    return true
    end
    end
    false
    end
    end

    def
    update(params)
    run_callbacks :update do
    update_model_attributes(params)
    if valid?
    entity = build_entity
    self.class.retry_on_exception? { CloudDatastore.dataset.save(entity) }
    else
    false
    end
    end
    end

    def
    destroy
    run_callbacks :destroy do
    key = CloudDatastore.dataset.key(self.class.name, id)
    self.class.retry_on_exception? { CloudDatastore.dataset.delete(key) }
    end
    end

    # Methods defined here will be class methods whenever we 'include DatastoreUtils'.
    module ClassMethods
    # Queries all objects from Cloud Datastore by named kind and using the provided options.
    #
    # @param [Hash] options the options to construct the query with.
    #
    # @option options [Google::Cloud::Datastore::Key] :ancestor filter for inherited results
    # @option options [Hash] :where filter, Array in the format [name, operator, value]
    #
    # @return [Array<Model>] an array of ActiveModel results.
    def all(options = {})
    query = CloudDatastore.dataset.query(name)
    query.ancestor(options[:ancestor]) if options[:ancestor]
    query_property_filter(query, options)
    entities = retry_on_exception { CloudDatastore.dataset.run(query) }
    from_entities(entities.flatten)
    end

    # Queries objects from Cloud Datastore in batches by named kind and using the provided options.
    # When a limit option is provided queries up to the limit and returns results with a cursor.
    #
    # @param [Hash] options the options to construct the query with. See build_query for options.
    #
    # @return [Array<Model>, String] an array of ActiveModel results and a cursor that can be used
    # to query for additional results.
    def find_in_batches(options = {})
    next_cursor = nil
    query = build_query(options)
    if options[:limit]
    entities = retry_on_exception { CloudDatastore.dataset.run(query) }
    next_cursor = entities.cursor if entities.size == options[:limit]
    else
    entities = retry_on_exception { CloudDatastore.dataset.run(query) }
    end
    model_entities = from_entities(entities.flatten)
    return model_entities, next_cursor
    end

    # Retrieves an entity by key and by an optional parent.
    #
    # @param [Integer or String] id_or_name id or name value of the entity Key.
    # @param [Google::Cloud::Datastore::Key] parent the parent Key of the entity.
    #
    # @return [Entity, nil] a Google::Cloud::Datastore::Entity object or nil.
    def find_entity(id_or_name, parent = nil)
    key = CloudDatastore.dataset.key(name, id_or_name)
    key.parent = parent if parent
    retry_on_exception { CloudDatastore.dataset.find(key) }
    end

    # Find object by ID.
    #
    # @return [Model, nil] an ActiveModel object or nil.
    def find(id)
    entity = find_entity(id.to_i)
    from_entity(entity)
    end

    # Find object by parent and ID.
    #
    # @return [Model, nil] an ActiveModel object or nil.
    def find_by_parent(id, parent)
    entity = find_entity(id.to_i, parent)
    from_entity(entity)
    end

    def
    from_entities(entities)
    entities.map { |entity| from_entity(entity) }
    end

    # Translates between Google::Cloud::Datastore::Entity objects and ActiveModel::Model objects.
    #
    # @param [Entity] entity from Cloud Datastore
    # @return [Model] the translated ActiveModel object.
    def from_entity(entity)
    return if entity.nil?
    model_entity = new
    model_entity.id = entity.key.id unless entity.key.id.nil?
    model_entity.id = entity.key.name unless entity.key.name.nil?
    entity.properties.to_hash.each do |name, value|
    model_entity.send "#{name}=", value
    end
    model_entity.reload!
    model_entity
    end

    def
    exclude_from_index(entity, boolean)
    entity.properties.to_h.keys.each do |value|
    entity.exclude_from_indexes! value, boolean
    end
    end

    # Constructs a Google::Cloud::Datastore::Query.
    #
    # @param [Hash] options the options to construct the query with.
    #
    # @option options [Google::Cloud::Datastore::Key] :ancestor filter for inherited results
    # @option options [String] :cursor sets the cursor to start the results at
    # @option options [Integer] :limit sets a limit to the number of results to be returned
    # @option options [String] :order sort the results by property name
    # @option options [String] :desc_order sort the results by descending property name
    # @option options [Array] :select retrieve only select properties from the matched entities
    # @option options [Hash] :where filter, Array in the format [name, operator, value]
    #
    # @return [Query] a datastore query.
    def build_query(options = {})
    query = CloudDatastore.dataset.query(name)
    query_options(query, options)
    end

    def
    retry_on_exception?
    retry_count = 0
    sleep_time = 0.5 # 0.5, 1, 2, 4 second between retries
    begin
    yield
    rescue
    => e
    puts "\e[33m[#{e.message.inspect}]\e[0m"
    puts 'Rescued exception, retrying...'
    sleep sleep_time
    sleep_time *= 2
    retry_count += 1
    return false if retry_count > 3
    retry
    end
    true
    end

    def
    retry_on_exception
    retry_count = 0
    sleep_time = 0.5 # 0.5, 1, 2, 4 second between retries
    begin
    yield
    rescue
    => e
    puts "\e[33m[#{e.message.inspect}]\e[0m"
    puts 'Rescued exception, retrying...'
    sleep sleep_time
    sleep_time *= 2
    retry_count += 1
    raise e if retry_count > 3
    retry
    end
    end

    def
    log_google_cloud_error
    yield
    rescue
    Google::Cloud::Error => e
    puts "\e[33m[#{e.message.inspect}]\e[0m"
    raise e
    end

    # private

    def query_options(query, options)
    query.ancestor(options[:ancestor]) if options[:ancestor]
    query.cursor(options[:cursor]) if options[:cursor]
    query.limit(options[:limit]) if options[:limit]
    query_sort(query, options)
    query.select(options[:select]) if options[:select]
    query_property_filter(query, options)
    end

    # Adds sorting to the results by a property name if included in the options.
    def query_sort(query, options)
    query.order(options[:order]) if options[:order]
    query.order(options[:desc_order], :desc) if options[:desc_order]
    query
    end

    # Adds property filters to the query if included in the options.
    # Accepts individual or nested Arrays:
    # [['superseded', '=', false], ['email', '=', 'something']]
    def query_property_filter(query, options)
    if options[:where]
    opts = options[:where]
    if opts[0].is_a?(Array)
    opts.each do |opt|
    query.where(opt[0], opt[1], opt[2]) unless opt.nil?
    end
    else
    query.where(opts[0], opts[1], opts[2])
    end
    end
    query
    end
    end
    end

    ?

    轉載于:https://www.cnblogs.com/sundongxiang/p/6237805.html

    總結

    以上是生活随笔為你收集整理的Rails下cloud datastore的使用的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。