Skip to content

Instantly share code, notes, and snippets.

@davinmsu
Created April 9, 2014 19:56
Show Gist options
  • Select an option

  • Save davinmsu/10308212 to your computer and use it in GitHub Desktop.

Select an option

Save davinmsu/10308212 to your computer and use it in GitHub Desktop.
class Order < ActiveRecord::Base
belongs_to :user
has_many :processed_orders
has_many :operations
has_many :documents, as: :reference
include HTTParty
base_uri ENV['VK_API_HOST']
enum type: {
unknown: 0,
like: 1,
share: 2,
join: 3
}
enum status: {
inactive: 0,
active: 1,
pending: 2,
completed_by_date: 3,
completed_by_count: 4,
cancelled_by_user: 5,
cancelled_by_object: 6,
cancelled_by_admin: 7,
completed: 8
}
enum obj_owner_type: {
vk_user: 0,
vk_group: 1
}
before_create :get_obj_details
after_create :activate!
enum_features :type, :status, :obj_owner_type
scope :exclude_processed, -> (user = nil) do
unless user.nil?
where(ProcessedOrder.where('order_id = orders.id AND user_id = ?', user.id).exists.not)
end
end
def accept(user)
inactive! and return if self.user.accounts.current.first.balance < price
processed_orders.create user: user
operations.create! user: user
increment!(:monitoring_operations_count, 1)
pending! unless monitoring_operations_count < count
end
def decline(user)
self.processed_orders.create user: user, status: :declined
end
def self.get_available(user)
a = exclude_processed(user).order(price: :desc)
x = 1
sum = (a.pluck(:price).collect { |b| b**x }).sum
weights = a.collect { |e| (e.price)**x/sum.to_f }
r = rand(1000).to_f/1000
k = 0
weights.each_with_index do |e,i|
k += e
return (a[i]) if k > r
end
nil
end
def set_to_pending_by_time
pending! if inactive? || active?
completed! if pending? && operations.empty?
end
# private
def activate!
self.delay(run_at: self.active_from).active!
self.delay(run_at: self.active_to).set_to_pending_by_time
self.delay(run_at: 20.seconds.from_now).check_object
self.delay(run_at: 20.seconds.from_now).check_operations
(get_vk_contractors & User.all.pluck(:ext_id)).each { |u| processed_orders.create user: User.find_by(ext_id: u), status: :existed }
end
def get_vk_contractors
users = []
method = 'likes.getList' if like? || share?
method = 'groups.getMembers' if join?
params = set_vk_params
loop do
response = self.class.get("/#{method}", query: params)
users.concat response['response']['users']
break if response['response']['users'].empty?
params.merge! offset: params[:offset] += (Rails.configuration.vk_request_count - Rails.configuration.vk_request_overlay)
end
users
end
def set_vk_params
params = {count: Rails.configuration.vk_request_count, offset: 0}
if like? || share?
params.merge! type: :post,
owner_id: vk_group? ? obj_owner_id * -1 : obj_owner_id,
item_id: obj_item_id,
friends_only: 0
end
params.merge! filter: :likes if like?
params.merge! filter: :copies if share?
params.merge! group_id: obj_owner_id if join?
params
end
def check_object
query = {posts: "#{(vk_group? ? '-' : '')}#{obj_owner_id}_#{obj_item_id}"}
cancelled_by_object! if self.class.get('/wall.getById', query: query)['response'].empty?
operations.each { |o| o.confirm }
self.delay(run_at: 20.seconds.from_now).check_operations if monitoring || pending?
end
def check_operations
operations.monitoring.where(user_id: operations.monitoring.pluck(:user_id) - get_vk_contractors).each { |o| o.fail }
self.delay(run_at: 20.seconds.from_now).check_operations if monitoring || pending?
end
def get_obj_details
key = obj_url.match(/wall-?[0-9]+_[0-9]+/).to_s
return if key.blank?
self.obj_owner_type = :vk_group if key =~ /\Awall-/
self.obj_owner_id = key[/[0-9]+_/].gsub(/_/, '').to_i
self.obj_item_id = key[/_[0-9]+\Z/].gsub(/_/, '').to_i
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment