ActiveResource::ResourceNotFound: Failed. Response code = 404. Response message = Not Found

1.7k views Asked by At

Hi I'm working on a rails project, I updated the development database of my project recently. I had sqlite, now I have Postgres.

I have this method for my Product model:

  def self.update_products!
   ec_products = ElemetalCapital::Product.all
   transaction do
     ec_products.each do |ec_product|
        product = ElemetalCapitalProduct.where(id: ec_product.id).first_or_initialize
        product.spot_id = ec_product.spot
        product.goldtrex_markup ||= 1  # default to a 1% markup
        product.description = ec_product.description
        product.metal = ec_product.metal
        product.weight = ec_product.weight
        product.elemetal_capital_premium = ec_product.premiumBuy
        product.save!
      end
    end
  end

Before the Postgres update, the method was working properly. However, after the update I'm getting this error, how can I fix that problem:

[2] pry(main)> Product.update_products!
   (0.5ms)  BEGIN
  ElemetalCapitalProduct Load (0.5ms)  SELECT  "products".* FROM "products" WHERE "products"."type" IN ('ElemetalCapitalProduct') AND "products"."id" = $1  ORDER BY "products"."id" ASC LIMIT 1  [["id", "GKILO-OPM"]]
   (0.4ms)  ROLLBACK
ActiveResource::ResourceNotFound: Failed.  Response code = 404.  Response message = Not Found.
from /Users/enriquesalceda/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/activeresource-4.0.0/lib/active_resource/connection.rb:144:in `handle_response'

Something that is very strange on the is the "products"."id" = $1, it shouldn't be $1.

This app use the API of a supplier elemetal capital, which provides the info about their products, and prices, then after a few calculations we update the shopify database. Just for the record:

This is my entire Product model:

class Product < ActiveRecord::Base
  self.primary_key = :id

  monetize :elemetal_capital_premium_cents, allow_nil: true

  belongs_to :spot

  def to_hash
    instance_variables.each_with_object({}) do |var, hash|
      hash[var.to_s.delete("@")] = instance_variable_get(var)
    end
  end

  def metal_name
    case metal
    when "Ag" then "Silver"
    when "Au" then "Gold"
    when "Pd" then "Palladium"
    when "Pt" then "Platinum"
    end
  end

  def price
    # return 1300 if spot.nil?

    spot_price = spot.ask
    ec_price = spot_price + elemetal_capital_premium
    total_price = ec_price * weight
    gt_price = total_price + (goldtrex_markup / 100 * total_price)
    gt_price.exchange_to(:AUD)
  end

  def shopify_variant_data
    {
      barcode: id,
      price: price.to_s,
      weight: weight,
      weight_unit: "oz",
      grams: weight * 31.1034768
    }
  end

  before_create :shopify_create

  def shopify_create
    data = {
      title: "#{metal_name} - #{description}",
      variants: [
        shopify_variant_data
      ]
    }
    sp = ShopifyAPI::Product.create(data)
    self.shopify_id = sp.id
  end

  before_update :shopify_update

  def shopify_update
    sp = ShopifyAPI::Product.find(shopify_id)
    variant = sp.variants.first
    shopify_variant_data.each do |k, v|
      instance_variable_set("@#{k.to_s}".to_sym, v)
    end
    variant.save!
  end

  def self.update_products!
    ec_products = ElemetalCapital::Product.all
    transaction do
      ec_products.each do |ec_product|
        product = ElemetalCapitalProduct.where(id: ec_product.id).first_or_initialize
        product.spot_id = ec_product.spot
        product.goldtrex_markup ||=  # default to a 1% markup
        product.description = ec_product.description
        product.metal = ec_product.metal
        product.weight = ec_product.weight
        product.elemetal_capital_premium = ec_product.premiumBuy
        product.save!
      end
    end
  end
end

This is the schema:

ActiveRecord::Schema.define(version: 20150609085027) do

  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"

  create_table "deliveries", force: :cascade do |t|
    t.string   "receiver"
    t.datetime "delivery_day"
    t.string   "tracking_number"
    t.text     "delivery_notes"
    t.datetime "created_at",      null: false
    t.datetime "updated_at",      null: false
    t.integer  "ticket_id"
  end

  create_table "elemetal_capital_trades", force: :cascade do |t|
    t.string  "location"
    t.string  "currency"
    t.string  "side"
    t.string  "elemetal_capital_product_id"
    t.integer "quantity"
    t.string  "elemetal_capital_trade_id"
    t.float   "price_per_unit"
    t.float   "weight"
    t.float   "price_per_weight"
    t.float   "price_total"
    t.string  "time_stamp_origin"
    t.string  "metal"
    t.float   "spot"
    t.integer "line_item_id"
  end

  add_index "elemetal_capital_trades", ["line_item_id"], name: "index_elemetal_capital_trades_on_line_item_id", using: :btree

  create_table "employees", force: :cascade do |t|
    t.string   "first_name"
    t.string   "last_name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "items", force: :cascade do |t|
    t.integer  "quantity"
    t.string   "item_description"
    t.float    "unit_price"
    t.datetime "created_at",       null: false
    t.datetime "updated_at",       null: false
    t.integer  "ticket_id"
  end

  create_table "line_items", force: :cascade do |t|
    t.integer  "quantity"
    t.integer  "shopify_line_item_id"
    t.integer  "order_id"
    t.datetime "created_at",                     null: false
    t.datetime "updated_at",                     null: false
    t.integer  "shopify_product_id",   limit: 8
  end

  add_index "line_items", ["order_id"], name: "index_line_items_on_order_id", using: :btree

  create_table "orders", force: :cascade do |t|
    t.integer  "order_number"
    t.integer  "shopify_order_id"
    t.integer  "total"
    t.datetime "created_at",       null: false
    t.datetime "updated_at",       null: false
  end

  create_table "payments", force: :cascade do |t|
    t.datetime "value_date"
    t.integer  "reference_number"
    t.float    "contract_rate",    default: 0.0
    t.string   "trade_notes"
    t.datetime "created_at",                     null: false
    t.datetime "updated_at",                     null: false
    t.integer  "ticket_id"
    t.float    "usd_payment",      default: 0.0
  end

  create_table "products", id: false, force: :cascade do |t|
    t.string   "id",                                       null: false
    t.string   "type",                                     null: false
    t.text     "description",                              null: false
    t.decimal  "weight",                                   null: false
    t.string   "metal",                                    null: false
    t.string   "spot_id",                                  null: false
    t.integer  "elemetal_capital_premium_cents"
    t.decimal  "goldtrex_markup",                          null: false
    t.datetime "created_at",                               null: false
    t.datetime "updated_at",                               null: false
    t.integer  "shopify_id",                     limit: 8, null: false
  end

  add_index "products", ["shopify_id"], name: "index_products_on_shopify_id", unique: true, using: :btree
  add_index "products", ["spot_id"], name: "index_products_on_spot_id", using: :btree

  create_table "spots", id: false, force: :cascade do |t|
    t.string  "id",        null: false
    t.integer "bid_cents", null: false
    t.integer "ask_cents", null: false
  end

  create_table "tickets", force: :cascade do |t|
    t.integer  "goldtrex_employee"
    t.string   "ticket_number"
    t.datetime "elemetal_capital_order_date"
    t.string   "trader"
    t.datetime "created_at",                  null: false
    t.datetime "updated_at",                  null: false
    t.boolean  "au"
    t.float    "au_spot_price"
    t.boolean  "ag"
    t.float    "ag_spot_price"
    t.boolean  "deposit"
    t.float    "deposit_amount"
  end

end
1

There are 1 answers

0
shlajin On

Rails uses ORM, which hides all logic of working with DB into nice methods. Basically that means that if you change the DB – nothing will happen, app will continue to work as expected (should mention, this statement does not applicable in any case as DBs differ, but not in this case). If you get 404 – it means item is missing in the database, nothing wrong about that.

When you said you changed DB from sqlite to Postgres – had you migrated the data? Try run ElemetalCapitalProduct.count from the console to ensure it has anything. If it does, compare data you had in sqlite and the data you receive in Postgres.