I followed tutorial how to integrate 3rd party api with a ruby on rails but I get an error
undefined method `map' for
{"number"=>12} permitted: false>:ActionController::Parameters
which points to request.rb
query_string = query.map{|k,v| "#{k}=#{v}"}.join("&") Full code
recipes_controller.rb
class RecipesController < ApplicationController def index @tag = query.fetch(:tags, 'all') @refresh_params = refresh_params @recipes, @errors = Spoonacular::Recipe.random(query, clear_cache) end def show @recipe = Spoonacular::Recipe.find(params[:id]) end private def query params.permit(:query).fetch(:query, {}) end def clear_cache params[:clear_cache].present? end def refresh_params refresh = { clear_cache: true } refresh.merge!({ query: query }) if query.present? refresh end end app/services/spoonacular/recipes.rb
module Spoonacular class Recipe < Base attr_accessor :aggregate_likes, :dairy_free, :gluten_free, :id, :image, :ingredients, :instructions, :ready_in_minutes, :title, :vegan, :vegetarian MAX_LIMIT = 12 CACHE_DEFAULTS = { expires_in: 7.days, force: false } def self.random(query = {}, clear_cache) cache = CACHE_DEFAULTS.merge({ force: clear_cache }) response = Spoonacular::Request.where('recipes/random', cache, query.merge({ number: MAX_LIMIT })) recipes = response.fetch('recipes', []).map { |recipe| Recipe.new(recipe) } [ recipes, response[:errors] ] end def self.find(id) response = Spoonacular::Request.get("recipes/#{id}/information", CACHE_DEFAULTS) Recipe.new(response) end def initialize(args = {}) super(args) self.ingredients = parse_ingredients(args) self.instructions = parse_instructions(args) end def parse_ingredients(args = {}) args.fetch("extendedIngredients", []).map { |ingredient| Ingredient.new(ingredient) } end def parse_instructions(args = {}) instructions = args.fetch("analyzedInstructions", []) if instructions.present? steps = instructions.first.fetch("steps", []) steps.map { |instruction| Instruction.new(instruction) } else [] end end end end app/services/spoonacular/base.rb
module Spoonacular class Base attr_accessor :errors def initialize(args = {}) args.each do |name, value| attr_name = name.to_s.underscore send("#{attr_name}=", value) if respond_to?("#{attr_name}=") end end end end app/services/spoonacular/request.rb
module Spoonacular class Request class << self def where(resource_path, cache, query = {}, options = {}) response, status = get_json(resource_path, cache, query) status == 200 ? response : errors(response) end def get(id, cache) response, status = get_json(id, cache) status == 200 ? response : errors(response) end def errors(response) error = { errors: { status: response["status"], message: response["message"] } } response.merge(error) end def get_json(root_path, cache, query = {}) query_string = query.map{|k,v| "#{k}=#{v}"}.join("&") path = query.empty?? root_path : "#{root_path}?#{query_string}" response = Rails.cache.fetch(path, expires_in: cache[:expires_in], force: cache[:force]) do api.get(path) end [JSON.parse(response.body), response.status] end def api Connection.api end end end end app/services/spoonacular/connection.rb
require 'faraday' require 'json' module Spoonacular class Connection BASE = 'https://spoonacular-recipe-food-nutrition-v1.p.mashape.com' def self.api Faraday.new(url: BASE) do |faraday| faraday.response :logger faraday.adapter Faraday.default_adapter faraday.headers['Content-Type'] = 'application/json' faraday.headers['X-Mashape-Key'] ='key' end end end end Thank you for any help.
RequestunderSpoonacular::Recipenamespace? And if it shouldnt be there did you try to refer to global scope with::Request.where(...)?request.rbcontains/spoonacular/recipe/so rails tries to resolveRequestconstant based on that::Request.where(...)work? Also I would suggest to moverequest.rbandconnection.rbtoapp/services/spoonacular/namespace. In that case you call it likeSpoonacular::Requestclass Requestwithmodule Spoonacularafter you moverequest.rb?