如何在Ruby on Rails API中以特定方式获取关联资源

时间:2015-11-17 23:25:59

标签: api ruby-on-rails-4

我必须对类进行建模:TBM和位置 TBM是父表,而位置是子表。 我有一个完全开发的RoR应用程序,我想开发一个API。 我开始为TBM开发API / V1控制器。

class Api::V1::TbmsController < Api::V1::BaseController
  before_filter :authenticate_user!
  before_action :set_tbm, only: [:show, :update]

  def index
    tbms = Tbm.order(:id)
    render json: tbms
  end 

  private
    def set_tbm
      @tbm = Tbm.find(params[:id])
    end

    def tbm_params
      params.require(:tbm).permit(:tbm_name, :chainage_direction).delete_if{ |k,v| v.nil? }
    end
end

我希望索引方法在检索两个TBM时,还包括子表位置中每个TBM的位置,并按每日降序排序(从最近日期开始枚举的位置)。 TBM已按其ID升序排序(如返回的JSON中所示)。

这是我的表的结构:

tbms
                                         Table "public.tbms"
       Column       |            Type             |                     Modifiers                     
--------------------+-----------------------------+---------------------------------------------------
 id                 | integer                     | not null default nextval('tbms_id_seq'::regclass)
 created_at         | timestamp without time zone | 
 updated_at         | timestamp without time zone | 
 tbm_name           | character varying(255)      | 
 chainage_direction | character varying(255)      | 
Indexes:
    "tbms_pkey" PRIMARY KEY, btree (id)
    "index_tbms_on_tbm_name" UNIQUE, btree (tbm_name)

locations
                                     Table "public.locations"
   Column   |            Type             |                       Modifiers                        
------------+-----------------------------+--------------------------------------------------------
 id         | integer                     | not null default nextval('locations_id_seq'::regclass)
 tbm_id     | integer                     | 
 created_at | timestamp without time zone | 
 updated_at | timestamp without time zone | 
 daily_date | date                        | not null
 station    | numeric(10,3)               | not null
 tbm_status | character varying(255)      | not null
 latitude   | numeric(12,8)               | 
 longitude  | numeric(12,8)               | 
Indexes:
    "locations_pkey" PRIMARY KEY, btree (id)
    "index_locations_on_tbm_id_and_daily_date" UNIQUE, btree (tbm_id, daily_date)
    "index_locations_on_tbm_id" btree (tbm_id)
    "index_locations_on_tbm_id_and_station" btree (tbm_id, station)

curl命令是:

curl -i -X GET \
   -H "Authorization:Token token=\"mytoken\", email=\"myemail@gmail.com\"" \
   -H "Content-Type:application/json" \
 'http://localhost:3000/api/v1/tbms/'

返回的JSON是:

{
"tbms":[
{
"id": 1,
"tbm_name": "Denis",
"chainage_direction": "Ascending",
"created_at": "2014-11-13T19:00:00-05:00",
"updated_at": "2015-11-16T17:36:10-05:00"
},
{
"id": 2,
"tbm_name": "Lea",
"chainage_direction": "Ascending",
"created_at": "2014-11-13T19:00:00-05:00",
"updated_at": "2015-11-04T15:27:54-05:00"
}
]
}

我正在使用Restlet的Chrome扩展程序DHC测试我的API。

1 个答案:

答案 0 :(得分:0)

解决方案依赖于位置控制器和嵌套路由:

  #api
  namespace :api do
    namespace :v1 do
      resources :users,     only: [:index, :create, :show, :update, :destroy]
      resources :sessions,  only: [:create]
      resources :tbms,      only: [:index, :edit, :update, :show] do
        resources :locations, only: [:index, :show]
      end
      resources :locations, only: [:index, :create, :show, :update, :destroy]
    end
  end

更改位置控制器以接受索引方法的参数:

class Api::V1::LocationsController < Api::V1::BaseController
  before_filter :authenticate_user!
  before_action :set_location, only: [:show, :update, :destroy]

  def index
    if params[:tbm_id]
      locations = Location.where("tbm_id = '#{params[:tbm_id]}'").order("daily_date DESC")
    else
      locations = Location.order("daily_date DESC, tbm_id")
    end
    #locations = apply_filters(locations, params)
    render json: locations
  end

  def show
    render json: @location
  end

  def update
    if @location.update(location_params)
      render json: @location, status: 200, location: api_v1_location_path(@location.id)
    else
      return api_error(status: 422, errors: @location.errors)
    end
  end

  def create
    location = Location.new(location_params)
    if location.save!
      render json: location, status: 201, location: api_v1_location_path(location.id)
    else
      return api_error(status: 422, errors: location.errors)
    end
  end

  def destroy
    if @location.destroy
        head status: 204
    else
      return api_error(status: 422, errors: @location.errors)
    end
  end

  private
    def set_location
      @location = Location.find(params[:id])
    end

    def location_params
      params.require(:location).permit(:tbm_id, :daily_date, :station, :tbm_status, :latitude, :longitude).delete_if{ |k,v| v.nil? }
    end
end

生成这种HTTP请求:

curl -i -X GET \
   -H "Authorization:Token token=\"mytoken\", email=\"myemail@gmail.com\"" \
   -H "Content-Type:application/json" \
 'http://localhost:3000/api/v1/tbms/1/locations/'

问题解决了。