ruby on rails - How to make data saved in database expire after a time period? -


i'm building store in rails. store has orders, order_items, users..

right when customer adds order_item cart, order unique id created automatically, , order_items saved under order_items model. there validation saying 3 order_items allowed in 1 order.

if possible, remove order_items saved model after 30 days. 30 days counter should start after saving 3 order_items.

how can achieve this?

thanks

class order < activerecord::base   belongs_to :order_status   belongs_to :user   has_many :order_items   validates_length_of :order_items, maximum: 3 #only 3 order_items allowed within order each user   before_create :set_order_status   before_save :update_subtotal      def subtotal     order_items.collect { |oi| oi.valid? ? (oi.quantity * oi.unit_price) : 0 }.sum   end private   def set_order_status     self.order_status_id = 1   end    def update_subtotal     self[:subtotal] = subtotal   end    end 

order_item.rb

class orderitem < activerecord::base   belongs_to :product   belongs_to :order   validates_associated :order   validates :quantity, presence: true, numericality: { only_integer: true, greater_than: 0 }   validate :product_present   validate :order_present     before_save :finalize    def unit_price     if persisted?       self[:unit_price]     else       product.price     end   end    def total_price     unit_price * quantity   end  private   def product_present     if product.nil?       errors.add(:product, "is not valid or not active.")     end   end    def order_present     if order.nil?       errors.add(:order, "is not valid order.")     end   end    def finalize     self[:unit_price] = unit_price     self[:total_price] = quantity * self[:unit_price]   end   end 

order_items_controller.rb

class orderitemscontroller < applicationcontroller  def create   @order = current_order   @order_item = @order.order_items.new(order_item_params)   @order.user_id = current_user.id   @order.save   session[:order_id] = @order.id     respond_to |format|     format.js { flash[:notice] = "order has been created." }    end end      def update     @order = current_order     @order_item = @order.order_items.find(params[:id])     @order_item.update_attributes(order_item_params)     @order_items = @order.order_items   end      def destroy     @order = current_order     @order_item = @order.order_items.find(params[:id])     @order_item.destroy     @order_items = @order.order_items   end   private    def order_item_params     params.require(:order_item).permit(:quantity, :product_id, :user_id)   end end 

schema.rb

create_table "order_items", force: :cascade |t|     t.integer  "product_id"     t.integer  "order_id"     t.decimal  "unit_price",  precision: 12, scale: 3     t.integer  "quantity"     t.decimal  "total_price", precision: 12, scale: 3     t.datetime "created_at",                           null: false     t.datetime "updated_at",                           null: false     t.boolean  "has_ordered"   end  create_table "orders", force: :cascade |t|     t.decimal  "subtotal",             precision: 12, scale: 3     t.decimal  "tax",                  precision: 12, scale: 3     t.decimal  "shipping",             precision: 12, scale: 3     t.decimal  "total",                precision: 12, scale: 3     t.integer  "order_status_id"     t.datetime "created_at",                                    null: false     t.datetime "updated_at",                                    null: false     t.integer  "user_id"     t.boolean  "ordered"     t.date     "first_item_added_at"     t.date     "first_order_added_at"   end 

one common way of approaching problem having background process periodically checking database , doing maintenance work necessary (cleaning, calculating intermediate results, etc.).

one simplistic solution checks orders @ least 3 order items , deletes items older 30 days below.

with rails put following under config/initializers/order_cleaner.rb, gets loaded every time start rails application.

thread.new   while true     # orders @ least 3 order_items     orders = orders.joins(:order_items).group('orders.id').having('count(order_id) >= 3')     orders.each |o|       # delete associated order_item if it's older 30 days       o.order_items.each {|oi| oi.destroy! if oi.updated_at < 30.days.ago }     end     sleep 1.minute   end end 

couple notes:

  1. if orders table gets bigger, practical in database without creating activerecord model instances , separate queries every orderitem
  2. for more complicated scheduling , job retrying using sidekiq or rufus scheduler worth considering
  3. more sophisticated solution require cleanup thread, logging , taking care multiple instances don't started (e.g. when you're using unicorn load balance app)

Comments

Popular posts from this blog

Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.12:test (default-test) on project.Error occurred in starting fork -

windows - Debug iNetMgr.exe unhandle exception System.Management.Automation.CmdletInvocationException -

configurationsection - activeMq-5.13.3 setup configurations for wildfly 10.0.0 -