Подтвердить что ты не робот

Как обновить один атрибут без атрибута update_at touch?

Как я могу это достичь?

попытался создать 2 метода, называемых

def disable_timestamps
  ActiveRecord::Base.record_timestamps = false
end

def enable_timestamps
  ActiveRecord::Base.record_timestamps = true
end

и самого метода обновления:

def increment_pagehit
  update_attribute(:pagehit, pagehit+1)
end

Включение и выключение временных меток с помощью обратных вызовов, таких как:

before_update :disable_timestamps, :only => :increment_pagehit
after_update :enable_timestamps, :only => :increment_pagehit

но он ничего не обновляет, даже желаемый атрибут (pagehit).

Любые советы? Я не хочу создавать другую таблицу только для подсчета изображений на странице.

4b9b3361

Ответ 2

В качестве альтернативы update_attribute, в Rails 3.1+ вы можете использовать update_column.

update_attribute пропускает проверки, но коснется updated_at и выполнит обратные вызовы.

update_column пропускает проверки, не касается updated_at и не выполняет обратные вызовы.

Таким образом, update_column - отличный выбор, если вы не хотите влиять на updated_at и не нуждаетесь в обратных вызовах.

Подробнее см. http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html.

Также обратите внимание, что update_column обновит значение атрибута в модели в памяти и не будет помечено как грязное. Например:

p = Person.new(:name => "Nathan")
p.save
p.update_column(:name, "Andrew")
p.name == "Andrew" # True
p.name_changed? # False

Ответ 3

Если все, что вы хотите сделать, это увеличить счетчик, я бы использовал вместо этого метод increment_counter:

ModelName.increment_counter :pagehit, id

Ответ 4

Чтобы избежать Monkeypatchingtroubles, вы также можете использовать ModelName.update_all для этой цели:

def increment_pagehit
  self.class.update_all({ pagehit: pagehit+1 }, { id: id })
end

Это также не касается временных меток в записи.

Ответ 5

не рекомендуется делать это:

self.class.update_all({ pagehit: pagehit+1 }, { id: id })

он должен быть

self.class.update_all("pagehit = pagehit + 1", { id: id })

причина в том, что если два запроса параллельны, в первой версии оба будут обновлять идентификаторы страниц с тем же номером, так как он использует номер, сохраненный в памяти Ruby. Второй вариант использует sql-сервер для увеличения числа на 1, в случае, если два из этих запросов приходят одновременно, сервер будет обрабатывать их один за другим и в итоге будет иметь правильное количество страниц.

Ответ 6

У вас также есть decrement и increment (и их версии), которые не изменяют updated_at, не запускают проверки обратных вызовов проверки и, очевидно, удобны для счетчиков/целых чисел.

Ответ 7

Если точность не так важна, и вы не ожидаете, что код будет работать много раз, вы можете попробовать изменить сохраненное в базе данных значение updated_at, например:

u = User.first
u.name = "Alex 2" # make some changes...
u.updated_at = u.updated_at + 0.000001.second # alter updated_at
u.save

чтобы Rails фактически попытался сохранить одно и то же значение, а не заменить его на Time.now.