The goal is to create an activity or update its counter if it's already present. And to be super accurate, the code avoids race conditions with a custom insert_on_duplicate_key_update
MySQL query.
All user activities are already preloaded, so in case the service knows that there was an existing activity it will just do an update counter+1 query. Additionally, the code has to check whether the given activity_name
is valid, which it does by specifying validators on the Activity ActiveRecord
class.
How can these be cleaner?
B (code I am currently using)
class ActivitiesService def store_activity(activity_name) (activities[activity_name] || Activity.new(user_id: id, name: activity_name)).complete end end class Activity < Active::Record def complete return self.class.increment_counter(:count, id) if persited? insert_on_duplicate_key_update if valid? @new_record = false end end
A (alternative rewritten code)
class ActivtiesService def store_activity(activity_name) if has_activity?(activity_name) Activity.increment_counter(:count, user_id) else Activity.complete(user_id: user_id, name: activity_name) end end end clas Acttivity < Active::Record def self.complete(args) insert_on_duplicate_key_update if new(args).valid? end end
insert_on_duplicate_key_update
stays actually for a custom sql query execution which performs anINSERT ... ON DUPLICATE KEY UPDATE ... mysql query
\$\endgroup\$