如何使用rails 4中的rest-client以两种方式在两个Rails应用程序之间共享数据

时间:2015-12-29 05:40:00

标签: ruby-on-rails ruby-on-rails-4

方案:

假设我有两个Rails应用程序 App1 App2 。 App2从App1通过rest-client获取数据。这两个应用程序都有几乎常见的模型,它们使用单​​独的 DB 。每当模型属性在App1中更新时,它们都会在App2中获取。

目标:

现在我需要执行 反向 ,即每当模型属性在 App2 中更新时,需要在 App1 DB 中获取和更新。

我无法找到这样做的方法。任何帮助,将不胜感激。

以下是从App1到App2获取数据所涉及的一些基本代码。

#app/controllers/application_controller.rb(App2)
class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception
  before_filter :authenticate_user!

  require 'rest_client'

  App1_API_TOKEN = Rails.application.secrets[:app1_api_token] # needed to access the APi
  API_BASE_URL = Rails.application.secrets[:app1_base_api_url] # base url of the API
  FULL_AUTH_FIELD = "Token " + App1_API_TOKEN
  RENTERS_URI = "#{API_BASE_URL}/renters.json"
  OWNERS_URI = "#{API_BASE_URL}/owners.json"
  PROPERTIES_URI = "#{API_BASE_URL}/properties.json"
  OWNERS_REST_RESOURCE = RestClient::Resource.new(OWNERS_URI, :headers => {:Authorization => FULL_AUTH_FIELD})
  RENTERS_REST_RESOURCE = RestClient::Resource.new(RENTERS_URI, :headers => {:Authorization => FULL_AUTH_FIELD})
  PROPERTIES_REST_RESOURCE = RestClient::Resource.new(PROPERTIES_URI, :headers => {:Authorization => FULL_AUTH_FIELD})
  OWNERS = OWNERS_REST_RESOURCE.get
  RENTERS = RENTERS_REST_RESOURCE.get
  PROPERTIES = PROPERTIES_REST_RESOURCE.get
end

其中一个控制器代码使用上面定义的常量。

#app/controller/premium_listings_controller.rb(App2)
class PremiumListingsController < ApplicationController
  # before_action :set_premium_listing, only: [:show, :edit, :update, :destroy]

  # GET /premium_listings
  # GET /premium_listings.json
  def index
    @owner = JSON.parse(OWNERS, :symbolize_names => true)
    @renter = JSON.parse(RENTERS, :symbolize_names => true)
    # TODO LOWP make this properites query filterable by status
    @premium_listings = JSON.parse(PROPERTIES, :symbolize_names => true)
  end

  # GET /premium_listings/1
  # GET /premium_listings/1.json
  def show
    property_uri = "#{API_BASE_URL}/properties/" + params[:id]
    property_rest_resource = RestClient::Resource.new(property_uri, :headers => {:Authorization => FULL_AUTH_FIELD})
    property = property_rest_resource.get
    @premium_listing = JSON.parse(property, :symbolize_names => true)
  end

  # GET /premium_listings/new
  def new
    # TODO HIGHP needs to be connected through API to create NEW PROPERTY on ROORAH
    @premium_listing = PremiumListing.new
  end

  # GET /premium_listings/1/edit
  def edit
  end

  # POST /premium_listings
  # POST /premium_listings.json
  def create
    @premium_listing = PremiumListing.new(premium_listing_params)

    respond_to do |format|
      if @premium_listing.save
        format.html { redirect_to @premium_listing, notice: 'Premium listing was successfully created.' }
        format.json { render :show, status: :created, location: @premium_listing }
      else
        format.html { render :new }
        format.json { render json: @premium_listing.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /premium_listings/1
  # PATCH/PUT /premium_listings/1.json
  def update
    respond_to do |format|
      if @premium_listing.update(premium_listing_params)
        format.html { redirect_to @premium_listing, notice: 'Premium listing was successfully updated.' }
        format.json { render :show, status: :ok, location: @premium_listing }
      else
        format.html { render :edit }
        format.json { render json: @premium_listing.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /premium_listings/1
  # DELETE /premium_listings/1.json
  def destroy
    @premium_listing.destroy
    respond_to do |format|
      format.html { redirect_to premium_listings_url, notice: 'Premium listing was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_premium_listing
      @premium_listing = PremiumListing.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def premium_listing_params
      params[:premium_listing]
    end
end

1 个答案:

答案 0 :(得分:2)

所以App2是App1的前端应用程序。要从App2更新App1记录,您需要在update中重写PremiumListingsController操作。它不应该更新App2 DB中的列表,而是应该向具有当前列表属性的App1发送PUT请求。获得响应后,它应该使用成功消息重定向到@premium_listing,或者使用错误消息呈现show(这就是它现在所做的)。

看起来应该是这样的:

def update
  property_uri = "#{API_BASE_URL}/properties/" + params[:id]
  property_rest_resource = RestClient::Resource.new(property_uri, :headers => {:Authorization => FULL_AUTH_FIELD})
  property_rest_resource.put(premium_listing_params)
  format.html { redirect_to @premium_listing, notice: 'Premium listing was successfully updated.' }
  format.json { render :show, status: :ok, location: @premium_listing }
rescue => e
  format.html { render :edit }
  format.json { render json: @premium_listing.errors, status: :unprocessable_entity }
end

(这只是一个展示这个想法的草图,不确定它是否有效)

App1应对update网址执行/properties/:id操作。此操作接受参数,更新数据库中的列表并返回200/204代码表示成功,或4**代码表示错误。当响应代码不是2**时,RestClient会引发异常。