方案:
假设我有两个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
答案 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会引发异常。