2010-08-03 2 views
0

Я использую RoR, и я хочу делать запросы на безопасное обновление в параллельном режиме. Например, когда у меня естьRuby On Rails: Как запускать безопасные обновления

var user = User.find(user_id) 
user.visits += 1 

я получаю следующий SQL код:

SELECT * FROM Users WHERE ID=1 -- find user's visits (1) 
UPDATE Users SET Visits=2 WHERE ID=1 -- 1+1=2 

Но если есть несколько запросов, происходящих в то же время, будет проблем с блокировками.

Согласно RoR API, я могу использовать: lock => true атрибут, но это не то, что я хочу.

я нашел удивительную функцию update_counters:

User.update_counters(my_user.id, :visits => 1) 

Это дает следующий код SQL

UPDATE Users SET Visits=Visits+1 WHERE [email protected] 

Работает отлично!

Теперь мой вопрос: как я могу переопределить функцию + =, чтобы вместо этого сделать update_counters?

Поскольку

user.visits += 1 # better 
User.update_counters(my_user.id, :visits => 1) # than this 

UPDATE

Я только что создал следующую функцию

class ActiveRecord::Base 

    def inc(column, value) 

    User.update_counters(self.id, column => value) 

    end 

end 

Существуют ли какие-либо другие лучшие идеи?

ответ

1

Не знаю о лучших идеях, но я бы определил этот метод для класса User, а не для ActiveRecord. И, может быть, increment_counter (который использует update_counters) сделает его более читаемым?

def inc(column, value) 
    self.increment_counter(column, value) 
end 

Не испытал это и не сказал, что это определенно лучшая идея, но, наверное, так я и сделал бы это.

Обновление: И AFAIK вы не можете переопределить «+ =», потому что «a + = b» просто ярлык для «a = a + b», и вы, вероятно, не хотите переопределять «=», использовать update_counters :)

+0

increment_counter увеличивает его на 1, иногда мне нужны разные значения. Спасибо в любом случае. – Alex