2013-09-20 3 views
0

У меня есть следующий метод в моей модели, который использует find_or_create_by, чтобы найти или создать новый продукт.Rails Dry up Найти или Создать

def self.save_prod(product) 
Product.find_or_create_by_prod_id(product) 
     product_data = ItemData.get_product_data(product) 
     p.update_attributes(
     :prod_id => product, 
     :upc => product_data[:upc], 
     :title => product_data[:title] 
     ) 
    end 

ItemData.get_product_data() метод представляет собой метод модуль, который называет API для получения данных о продукте:

def self.get_product_data(product) 
     url_raw = URI.parse("http://www.api.com/v1/itemid=#{product}") 
      url = Net::HTTP.get_response(url_raw).body 
      @resp = JSON.parse(url) 
      @title = Sanitize.clean(@resp["serviceResult"]["itemName"]).strip 
      @upc = @resp["serviceResult"]["uPC"] 
      {:title => @title, :upc => @upc} 
    end 

Это работает, как ожидалось, но я знаю, что это может быть намного более эффективным, по не называя ItemData.get_product_data() способ каждый раз save_prod() способ называется. Как я могу добавить новые данные продукта без необходимости звонить ItemData.get_product_data(), если продукт уже существует.

+0

- это возвращаемое значение API-вызова только для объекта продукта? Что такое p в атрибутах p.update? – AshwinKumarS

+0

API возвращает данные о возврате продукта (название и upc). объект продукта создается в методе 'save_prod'. – Yogzzz

+0

Проверьте мой ответ ниже. Почему вы хотите сделать вызов API для объекта, который вы сейчас создаете? Вы создаете пустые объекты в Product.find_or_create? – AshwinKumarS

ответ

1

Другой способ сделать это. Это вернет объект Product, если он уже присутствует, иначе он создаст его из api и вернет новый объект.

def self.save_prod(product) 
    Product.find_by_prod_id(product) || Product.create(ItemData.get_product_data(product)) 
end 

Изменить вызов апи вернуть хэш с prod_id. Не знаете, почему вы конвертируете title и upc в переменные класса здесь. Это может привести к проблемам, если они используются широко.

def self.get_product_data(product) 
    url_raw = URI.parse("http://www.api.com/v1/itemid=#{product}") 
     url = Net::HTTP.get_response(url_raw).body 
     @resp = JSON.parse(url) 
     @title = Sanitize.clean(@resp["serviceResult"]["itemName"]).strip 
     @upc = @resp["serviceResult"]["uPC"] 
     {:title => @title, :upc => @upc, :prod_id => product} 
end 
1

Вместо поиска или создания используйте поиск или инициализацию. Измените код следующим образом:

prod = find_or_initialize_by_prod_id(product) 
if prod.new_record? 
    prod.save! 
    product_data = ItemData.get_product_data(product) 
    prod.update_attributes(
    :prod_id => product, 
    :upc => product_data[:upc], 
    :title => product_data[:title] 
    ) 
end 

с помощью find_or_initalize вы можете различить, была ли создана или нашла запись с помощью new_record метода. Если вы новый, вы можете сохранить и сделать вызов API и делать все, что хотите.

Смежные вопросы