Rails 4: Плохо ли выполнять операции с базой данных в модели?

Скажем, у меня есть модель продукта (app/models/product.rb) и определение следующего метода в модели.

def update_stock product
  product.stock -= 1
  product.save(:validation => false)
end

Это приемлемо?

Заранее спасибо.


person fatman13    schedule 16.04.2014    source источник
comment
Как правило, выполнение операций с базой данных в модели не является плохой практикой. Этот код находится в Product? Это работает? Я ожидаю, что ему нужно self вместо product (технически второму, вероятно, не нужно ни то, ни другое)...   -  person Brad Werth    schedule 16.04.2014
comment
Методы класса должны ссылаться на self, и если это так, то это вполне приемлемо, учитывая факт Fat model и Skinny controller.   -  person Pavan    schedule 16.04.2014
comment
Между прочим, это в основном точный способ сделать это, за исключением того, что он кажется нарушением закона Деметры (en.wikipedia.org/wiki/Law_of_Demeter) и, вероятно, следует переместить в Product...   -  person Brad Werth    schedule 16.04.2014
comment
@Brad Werth - метод принимает объект product, он не предназначен для работы с self.   -  person Max Williams    schedule 16.04.2014
comment
@Max Williams - Да, не шучу, это то, что я комментировал. См. ответ Sevenseacat, как это сделать правильно...   -  person Brad Werth    schedule 16.04.2014


Ответы (4)


Мне это кажется подозрительным - вы говорите, что это метод в вашей модели продукта, но затем метод обновляет совершенно другой экземпляр продукта (тот, который вы передаете, а не тот, для которого вы вызываете метод).

Если бы это было что-то вроде:

class Product < ActiveRecord::Base
  def update_stock
    self.stock -= 1
    save
  end
end

Тогда это было бы куда уместнее. (update_stock также не кажется лучшим названием для метода, и пропускать проверки, вероятно, не очень хорошая идея.)

person sevenseacat    schedule 16.04.2014
comment
Метод принимает объект продукта. - person Max Williams; 16.04.2014
comment
Да, я знаю. Как я уже сказал, это не имеет смысла. - person sevenseacat; 16.04.2014

Это хорошая практика для сохранения операций базы данных и бизнес-логики приложения в модели. Модель напрямую взаимодействует с базой данных с помощью ORM (объектно-реляционное сопоставление). Также в соглашении о рельсах контроллер должен быть тонким, а модель - толстой. Этот ответ подробно объясняет это.

Что такое Ruby on Rails ORM с точки зрения непрофессионала? Пожалуйста, объясните

person Rajdeep Singh    schedule 16.04.2014

Если вы хотите обновить что-то лучшее, используйте update_attributes!

Можно написать так:

class Product < ActiveRecord::Base

  def update_stock product
   self.update_attributes!(stock:  stock - 1)
 end
end
person Rajarshi Das    schedule 16.04.2014
comment
Метод принимает объект продукта! Не могу поверить, что никто другой этого не заметил. - person Max Williams; 16.04.2014

Тебе решать!

Самый простой способ, который я использую, чтобы понять, как что-то делать, — это посмотреть на это с точки зрения модуля. Если у вас есть «тяжелый» код в контроллере, будете ли вы использовать этот код в другой области приложения?


Rails — это набор классов и модулей

Код доступен для разных частей приложения, в зависимости от того, какие модули вызываются. Если вы считаете, что повторное использование этого метода в разных областях приложения принесет вам пользу, вы должны включить либо экземпляр или метод класса в модели, так как это откроет этот метод для этих объектов

Я бы использовал код, предоставленный RSB и sevenseacat, возможно, используя метод decrement! в ответе sevenseacats:

self.decrement!(:stock)

Что касается вашего вопроса, я бы лично сделал это, но сделал бы его методом экземпляра. sevenseacat в основном объяснил, что я буду делать

person Richard Peck    schedule 16.04.2014