Reputation: 828
I am trying to use Rail's Serializer on a JSON object being returned by an API in a Rails API app. I need to authenticate, ingest the API, filter the data, and rebroadcast the filtered data. No view is required.
To filter the data, I am trying to implement the Serializer - it's clear I haven't set it up correctly though. I can see it is working and in place because it is adding the initial object in front of the data it is returning (see data below: serialized object starts with kobo_data
). But it is returning all the fields of data, not just the fields I'm trying to call. In this case I'm trying to return just the field prikey
, but it is returning all the fields of data.
I've tried to address issues in similar threads to this (ActiveModel::Serializer in Rails - serializer methods ignored in JSON result, rails active model serializer not doing anything, Using ActiveModel::Serializer in Rails - JSON data differs between json and index response), although since I don't have a .html view, I wonder if this might be related to the issue mentioned in the last link. But another tutorial I"ve done (https://thesocietea.org/2015/03/building-a-json-api-with-rails-part-2-serialization/) employs serialization in a Rails-API app without a view, so I'm guessing it's not.
Any suggestions on what I'm doing wrong and how I can fix it?
Model:
class KoboApi < ActiveRecord::Base
require 'rest_client'
USERNAME = ENV['KOBO_API_USER']
PASSWORD = ENV['KOBO_API_PWD']
SURVEY = ENV['KOBO_API_SURVEY']
# API_BASE_URL = "https://kc.kobotoolbox.org/api/v1/"
API_BASE_URL = "https://sg.smap.com.au/api/v1"
def self.get_api_info
uri = "#{API_BASE_URL}/data/#{SURVEY}?format=json"
rest_resource = RestClient::Resource.new(uri, USERNAME, PASSWORD)
response = rest_resource.get
JSON.parse response
end
end
Controller
class KoboDataController < ApplicationController
def index
@kobo_info = KoboApi.get_api_info
render json: @kobo_info
end
end
Application Controller
class ApplicationController < ActionController::API
include ActionController::Serialization
end
kobo_api_serializer.rb
class KoboApiSerializer < ActiveModel::Serializer
attributes :prikey
end
Gem file
source 'https://rubygems.org'
gem 'active_model_serializers', '~> 0.8.3'
gem 'rest-client'
gem 'pg'
gem 'rails', '4.2.5.1'
gem 'rails-api'
gem 'spring', :group => :development
# gem for environment variables
gem 'dotenv-rails', :groups => [:development, :test]
gem 'figaro'
Data returned
{"kobo_data":[{"prikey":"1","Upload Time":"2016-06-17 11:11:38.802+00","Version":"1","Complete":"t","Survey Notes":"","Location Trigger":"","deviceid":"webworm"....[data truncated]
Upvotes: 3
Views: 1814
Reputation: 828
I just spoke with someone who walked me through the problem I was having, not all of which was related to the code I posted above. Am posting some details here. Am sure there are other ways to fix this, but this is how we covered it. Hope it's helpful.
each_serializer
Specifically related to the language as posted above: I was not including reference to each_serializer
in my render
statement in my model. This issue is referenced in this thread here as well: rails active model serializer not doing anything.
controller
class KoboDataController < ApplicationController
def index
@kobo_info = KoboApi.get_api_info
@kobo_info.each do |kobo_info|
begin
#this pulls in new records that have been added to the api and adds them to the database. it doesn't pull in records from the api that are already in the db
KoboApi.find_or_create_by(lemurs_quantity: kobo_info['lemurs_quantity'], month_and_year: Date.parse(kobo_info['month_and_year']))
# some of my records don't have valid date values, so `rescue` is added to keep rails from returning a `notfound` page.
# quick tutorial here: http://www.rubytutorial.io/rails-rescue_from/
rescue
puts "rescued"
end
end
# I needed to update my render logic.
# see addition of `each_serializer` here.
# @kobo_info has also changed to KoboApi.all as well.
render(
json: KoboApi.all,
each_serializer: KoboApiSerializer
)
end
end
If my database had been configured correctly, this should have fixed it for me.
Also, just in case there was an issue with the Active Model Serializers
i was using, we updated my gem file to replace the line I had (gem 'active_model_serializers', '~> 0.8.3'
) with the following:
gem 'active_model_serializers', :git => 'git://github.com/AskNative/active_model_serializers.git', :branch => '0-8-stable'
However, I had an issue with the two-word table name I had created. I had created my table with a camelCase name structure, and rails was expecting separated_words (ie: with underscore).
You can see the table name here is koboApis
:
original migration
class KoboApis < ActiveRecord::Migration
def change
create_table :koboApis do |t|
t.integer :lemurs_quantity
t.date :month_and_year
t.text :_geolocation
t.text :lemur_category
end
end
end
You can see in my original schema that the table name is indeed kobo_apis
, and not `koboApis'.
schema
ActiveRecord::Schema.define(version: 20160620063545) do
create_table "kobo_apis", force: :cascade do |t|
t.integer "lemurs_quantity"
t.date "month_and_year"
t.text "_geolocation"
t.text "lemur_category"
end
end
The table Rails was expecting didn't even exist because of this.
We fixed this by running a second migration at the terminal: rails g migration RenameOldTableToNewTable
. I then added this logic to the new migration file: rename_table :koboApis, :kobo_apis
. Entire migration file here:
update migration file
class RenameOldTableToNewTable < ActiveRecord::Migration
def change
rename_table :koboApis, :kobo_apis
end
end
I ran rake db:drop db:create db:migrate
to update everything, and then my Rails Api page rendered correctly.
Upvotes: 5