class ReorderWorkflow attr_accessor :entity_classname, :column_name attr_accessor :entity_id, :src_index, :dst_index # This workflow is used by entities which has a "order" column of sort # Given: # entity_classname: the entity class name, e.g. PostStatus # column_name: the name of the db column that contains the order information, e.g. 'order' # entity_id: the id of the entity being reordered # src_index: the current order of the entity # dst_index: the new order of the entity # # The workflow reorders the record with id of entity # from to using as the db column that keeps the ordering # # Returns: # A collection of the reordered records, if successful # nil, if unsuccessful def initialize(entity_classname: "", column_name: "", entity_id: "", src_index: "", dst_index: "") @entity_classname = entity_classname @column_name = column_name @entity_id = entity_id @src_index = src_index @dst_index = dst_index end def run convert_indexes_to_i if src_index == dst_index return {} end lowest_index = src_index < dst_index ? src_index : dst_index highest_index = src_index < dst_index ? dst_index : src_index column_name_sanitized = ActiveRecord::Base.connection.quote_column_name(column_name) entity_records = entity_classname.where("#{column_name_sanitized} BETWEEN #{lowest_index} AND #{highest_index}") # reorder records entity_records.each do |entity_record| if entity_record.id == entity_id entity_record[column_name] = dst_index elsif src_index < dst_index entity_record[column_name] -= 1 elsif src_index > dst_index entity_record[column_name] += 1 end end # save all changes in a single transaction entity_classname.transaction do entity_records.each(&:save!) end return entity_records rescue return nil end def convert_indexes_to_i self.src_index = src_index.to_i self.dst_index = dst_index.to_i end end