Issue with getting my API Call in Rails to properly display correctly in views (Using HTTParty) -
i using httparty gem in rails make api call , has been successful. receive no errors after defining variables in controller can not loops produce anything.
if type in <%= @variable %> shows active record object expected. if same include variable.name provides string, not hoping. have followed several httparty tutorials , put in lot of api research can't seem figured out. trying retrieve list of snacks external api. here have (some of things in view test).
api call (i put in separate folder services):
class snackapi include httparty base_uri 'https://api-snacks.nerderylabs.com/v1/' snack_access = "/snacks?apikey=#{env['snack_api_key']}" def get_snacks response = self.class.get(snack_access) json.parse(response.body) end end
first time posting code snippets not sure how post in proper indentation, correct in application.
controller:
class snackscontroller < applicationcontroller def index @snacks = snack.all @permanent_snacks = snack.where(optional: false) @optional_snacks = snack.where(optional: true) end end
model:
class snack < applicationrecord validates :name, presence: true validates_uniqueness_of :name end
view (index.html.erb) in snacks folder:
<h1> welcome snafoo! </h1> <!-- attempting these loops display each snack item included in api nothing appears --> <% @permanent_snacks.each |snack| %> <%= snack.name %> <% end %> <% @optional_snacks.each |snack| %> <%= snack.name %> <% end %> <%= @snacks %> <%= @optional_snacks %> <%= @permanent_snacks %> <br /> snack name paramater (to test): <%= @snacks.name %> <!-- recognizes fields , datatypes -->
results in view: objects ( each one. expected this, test api retrieving info) <%= @snacks.name %> outputs snack @ least recognizing fields , datatypes in schema. main issue getting loops work , display each snack in api.
i have tried hours attempting resolve on own i'm @ point of frustration , appreciate point me in right direction.
if schema needed/helpful resolve can post too.
terminal output when load page (usually code on ubuntu coding on windows due issues partition:
started "/" 10.0.2.2 @ 2017-09-11 21:49:49 +0000 cannot render console 10.0.2.2! allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255 processing snackscontroller#index html rendering snacks/index.html.erb within layouts/application snack load (0.3ms) select "snacks".* "snacks" "snacks"."optional" = $1 [["optional", "f"]] snack load (0.5ms) select "snacks".* "snacks" "snacks"."optional" = $1 [["optional", "t"]] rendered snacks/index.html.erb within layouts/application (3.5ms) completed 200 ok in 401ms (views: 374.1ms | activerecord: 0.8ms)
start fixing client:
# place in /lib or app/clients not service object. # app/clients/snack_api.rb class snackapi include httparty base_uri 'https://api-snacks.nerderylabs.com/v1/' format :json def initialize(*opts) @options = opts.reverse_merge({ apikey: env['snack_api_key'] }) end def get_snacks response = self.class.get('/snacks', @options) end end
use format :json
instead of instead of parsing json response manually. important since if api errors out , returns empty response json.parse blows up:
irb(main):002:0> json.parse('') json::parsererror: 745: unexpected token @ ''
if want display articles straight api don't need model:
class snackscontroller < applicationcontroller def index response = snackapi.get_snacks if response.success? @snacks = response[:snacks] else flash.now[:error] = "could not fetch snacks" @snacks = [] end end end
otherwise create service object consume api:
# app/services/snack_import_service class snackimportservice attr_accessor :client def intialize(client = nil, **opts) # trick lets inject spy or double in tests @client = client || snackapi.new(opts) end def perform response = client.get_snacks # remember http requests can , fail if response.success? response[:snacks].map |data| snack.find_or_create_by!(name: data[:name]) end else rails.logger.error "snackapi request unsuccessful #{response.code}" end end end
having separate service object client idea adheres single responsibility principle , lets extract out client gem reusable component separate application logic.
class snackscontroller < applicationcontroller def index @snacks = snackimportservice.new.perform @permanent_snacks = snack.where(optional: false) @optional_snacks = snack.where(optional: true) end end
Comments
Post a Comment