Skip to content

Instantly share code, notes, and snippets.

@gnagel
Forked from jhjguxin/how_to_concerns.md
Created June 17, 2014 22:13
Show Gist options
  • Save gnagel/512951a4a12f2e3fe786 to your computer and use it in GitHub Desktop.
Save gnagel/512951a4a12f2e3fe786 to your computer and use it in GitHub Desktop.

http://www.zhlwish.com/2012/07/23/rails-activesupport-concern/

# autoload concerns
module YourApp
  class Application < Rails::Application
    # config.autoload_paths += %W(
    #     #{config.root}/app/controllers/concerns/
    #      #{config.root}/app/models/concerns/
    #   )
    config.autoload_paths += Dir[ Rails.root.join('app', 'models', "concerns", '**/') ]
    config.autoload_paths += Dir[ Rails.root.join('app', 'controllers', "concerns", '**/') ]  end
end
# app/models/concerns/trashable.rb
module Trashable
  extend ActiveSupport::Concern
  
  included do
    default_scope   where(trashed: false)
    scope :trashed, where(trashed: true)
  end
  
  def trash
    update_attribute :trashed, true
  end
end
# app/models/message.rb
class Message < ActiveRecord::Base
  include Trashable, Subscribable, Commentable, Eventable
end

# app/controllers/commend_calculate.rb
# encoding: UTF-8
module CommendCalculate
  extend ActiveSupport::Concern

  included do
    #before_filter :do_something
    # ....
  end

  # 智能推荐
  def smart_commend_users(user, exclude_users, paginate_params)
    normal_user_smart_commend(user, exclude_users, paginate_params)
  end

  #provider an user and exclude_users return an user list
  #users_similar(ids = [1,2,3],[1,2,3])
  def users_similar(user, exclude_users)

    hobbys_ids = user.Hobbys.split(",").collect{|h| h.first if h.present?}.uniq
    look_for_ids = user.Lookfor.split(",").collect{|h| h.first if h.present?}.uniq

    if hobbys_ids.present? and look_for_ids.present?
      hobbys_regexp_str = hobbys_ids.collect{|i| "#{i}0" << '\d|'}.join('').gsub(/\|$/, "")
      look_for_regexp_str = look_for_ids.collect{|i| "#{i}" << '|'}.join('').gsub(/\|$/, "")


      users = GxUser.desc(:active_score).where(Hobbys: /#{hobbys_regexp_str}/, Lookfor: /#{look_for_regexp_str}/ ).where({:UserID => {"$nin" => exclude_users}, :UserName => {"$ne" => ""}, :HeadImage => {"$ne" => nil}, :Status => "1", :IsOnline => "1"})
    end
  end

  def new_user_smart_commend(user, exclude_users, paginate_params)
    #users = GxUser.desc(:active_score)

    users = users_similar(hobbys_id, exclude_users)
    # 分页
    if paginate_params.present?
      user_paginate = MongoPaginator.new(users, paginate_params)
    else
      users
    end
  end

  # 智能推荐 主体函数 可接收 用户实例, 排除用户ids, 分页参数 示例见最下方测试代码
  def normal_user_smart_commend(user, exclude_users, paginate_params)
    if user.present? and user.is_a? GxUser
      users = GxCommendUser.desc(:relation_score).where({commend_user_id: {"$nin" => exclude_users}}).where({user_id: user.UserID})

      # 如果 没有 推送用户则 按新用户处理
      # users = users_same_hobby(user, exclude_users) unless users.present?
      unless users.present?
        user.generate_commend_users
        users = GxCommendUser.desc(:relation_score).where({commend_user_id: {"$nin" => exclude_users}}).where({user_id: user.UserID})
      end
      users
    end

    # 分页
    if paginate_params.present?
      user_paginate = MongoPaginator.new(users, paginate_params)
    else
      users
    end
  end

  # 可能认识
  def friend_users(user, exclude_users)
    if user.present? and user.is_a? GxUser
      GxUser.near(:GPS => user[:GPS]).where({:UserID => {"$nin" => exclude_users}, :UserName => {"$ne" => ""}, :HeadImage => {"$ne" => nil}, :Status => "1", :IsOnline => "1"})
    end
  end

  # 兴趣爱好
  def hobby_users(user, exclude_users)
    if user.present? and user.is_a? GxUser
      GxUser.near(:GPS => user[:GPS]).where({:UserID => {"$nin" => exclude_users}, :UserName => {"$ne" => ""}, :HeadImage => {"$ne" => nil}, :Status => "1", :IsOnline => "1"})
    end
  end

  # 附近的人
  # nearby_users(user, debug = "1", paginate_params = {pagesize: '10', pageindex: "1"})
  def nearby_users(user, exclude_users, debug = nil, paginate_params = {})
    if user.present? and user.is_a? GxUser
      if debug.eql? "1"
        users = GxUser.where({:UserID => {"$nin" => exclude_users}, :UserName => {"$ne" => ""}, :HeadImage => {"$ne" => nil}, :XjTag => "0", :Status => "1",:IsOnline => "1"}).sort(_id:-1)
      else
        users = GxUser.near(:GPS => user[:GPS]).where({:UserID => {"$nin" => exclude_users}, :UserName => {"$ne" => ""}, :HeadImage => {"$ne" => nil}, :Status => "1",:IsOnline => "1"})
      end

      # 分页
      if paginate_params.present?
        user_paginate = MongoPaginator.new(users, paginate_params)
      else
        users
      end
    end
  end

  # gender "0" "1"
  def nearby_single_gender_users(user, exclude_users, gender, paginate_params = {})
    users = GxUser.near(:GPS => user[:GPS]).where({:UserID => {"$nin" => exclude_users}, :UserName => {"$ne" => ""}, :HeadImage => {"$ne" => nil}, :Status => "1", :Gender => gender, :IsOnline => "1"})

    # 分页
    if paginate_params.present?
      user_paginate = MongoPaginator.new(users, paginate_params)
    else
      users
    end
  end

  # 格式化 commend_user_list 返回 由 user hash 组成的数组
  def format_commend_user_list(commend_user_list, noGPS = false)
    commend_users = []

    commend_user_list.each do |commend_user|
      if commend_user.is_a? GxCommendUser
        commend_user = GxUser.where(UserID: commend_user.commend_user_id).first
      end

      if commend_user.present?
        if noGPS
          commend_user.Distance= 999000
          commend_user.JLscore= commend_user.Distance
        end

        commend_users.append(commend_user.commend_user_hash)
      end
    end
    commend_users
  end

end
############################################
=begin
#test case should be better rspec or unit test
include CommendCalculate
user = GxUser.last
exclude_users = GxBlock.where({UserID: @userid}).distinct("TargetuserID")
exclude_users.concat([@userid, "1", "2"])
exclude_users.concat([user.UserID, "1", "2"])
paginate_params = {pagesize: "20", pageindex: "1"}

smart_commend_users(user, exclude_users, paginate_params).count
friend_users(user, exclude_users).count
hobby_users(user, exclude_users).count
nearby_users(user, exclude_users, debug = @debug).count
nearby_single_gender_users(user, exclude_users, gender ="0", paginate_params).count
=end
# encoding: UTF-8
module UserCommendable
extend ActiveSupport::Concern
included do
#has_many :memberships, as: :membershipable, dependent: :destroy
#after_create :create_owner_membership
#after_create :generate_commend_users
#field :active_score, type: Float
#field :update_userinfo_at, type: DateTime, default: ->{ DateTime.now }
#field :sort_index, type: Float # sort_index = active_score + GxRelationScore.get_score_list([self.UserID]) #排列分 因为是 关系分 和 活跃分之和
def self.statis_commend_user_ids(exclude_users)
#GxUser.where({:UserID => {"$nin" => exclude_users}, :UserName => {"$ne" => ""}, :HeadImage => {"$ne" => nil}, :Status => "1", :IsOnline => "1"}).desc(:active_score).limit(200)
cache_key = "recommend_statis_user_ids"
recommend_statis_user_ids = Rails.cache.read(cache_key)
if recommend_statis_user_ids.nil?
recommend_statis_user_ids = GxUser.where({:UserID => {"$nin" => exclude_users}, :UserName => {"$ne" => ""}, :HeadImage => {"$ne" => nil}, :Status => "1", :IsOnline => "1"}).desc(:active_score).only(:UserID).limit(200).entries.collect{|u| u.UserID}
Rails.cache.write(cache_key, recommend_statis_user_ids, :expires_in => 1.days)
end
recommend_statis_user_ids
end
end
def active_users(exclude_users)
#GxUser.desc(:active_score).limit(100)
list = []
criteria = GxUser.where({:UserID => {"$nin" => exclude_users}, :UserName => {"$ne" => ""}, :HeadImage => {"$ne" => nil}, :Status => "1", :IsOnline => "1"}).desc(:active_score)
5.times do |i|
list.concat(criteria.skip(i*20).limit(40).entries)
end
list
end
#provider an user and exclude_users return an user list
#users_similar(ids = [1,2,3],[1,2,3])
def users_similar(user = self, exclude_users)
users = GxUser.desc(:active_score).where({:UserID => {"$nin" => exclude_users}, :UserName => {"$ne" => ""}, :HeadImage => {"$ne" => nil}, :Status => "1", :IsOnline => "1"})
if user.Hobbys.present?
hobbys_ids = user.Hobbys.split(",").collect{|h| h.first if h.present?}.uniq
hobbys_regexp_str = hobbys_ids.collect{|i| "#{i}0" << '\d|'}.join('').gsub(/\|$/, "")
#users = users.where(Hobbys: /#{hobbys_regexp_str}/) if hobbys_regexp_str.present?
hobbys_ids.each do |id|
users = users.where(Hobbys: /#{id}0\d/)
end
end
if user.Lookfor.present?
look_for_ids = user.Lookfor.split(",").collect{|h| h.first if h.present?}.uniq
look_for_regexp_str = look_for_ids.collect{|i| "#{i}" << '|'}.join('').gsub(/\|$/, "")
#users =users.where(Lookfor: /#{look_for_regexp_str}/ ) if look_for_regexp_str.present?
look_for_ids.each do |id|
users = users.where(Lookfor: /#{id}/)
end
end
users
end
# 准备一个备选方案:准备固定的200个用户,预先设定关系度的值,新注册的用户就推这批固定的用户
def generate_statis_users
exclude_users = GxBlock.where({UserID: self.UserID}).distinct("TargetuserID")
#exclude_users << @userid
exclude_users.concat([self.UserID, "1", "2"])
recommend_statis_user_ids = GxUser.statis_commend_user_ids(exclude_users)
if recommend_statis_user_ids.present?
GxCommendUser.delete_all({user_id: self.UserID})
recommend_statis_user_ids.each do |recommend_user_id|
relation_score = rand(6..9.9).round(1)
GxCommendUser.create({
user_id: self.UserID,
relation_score: relation_score,
commend_user_id: recommend_user_id
})
end
end
end
# generate commend users for new user
def generate_commend_users
exclude_users = GxBlock.where({UserID: self.UserID}).distinct("TargetuserID")
#exclude_users << @userid
exclude_users.concat([self.UserID, "1", "2"])
recommend_users = users_similar(self, exclude_users).limit(100).entries
#recommend_users = active_users(exclude_users)
if recommend_users.present?
GxCommendUser.delete_all({user_id: self.UserID})
recommend_users.each do |recommend_user|
relation_score = self.get_static_relation_score({relation_user: recommend_user})
#relation_score = self.get_relation_score(recommend_user.UserID)
#relation_score = 1.0
GxCommendUser.create({
user_id: self.UserID,
relation_score: relation_score,
commend_user_id: recommend_user.UserID
})
end
end
end
# update single user's commend_user for old user
def update_single_user(user = nil)
user ||= self
GxCommendUser.delete_all(user_id: user.UserID)
#commend_user = GxCommendUser.desc(:_id).where(user_id: user.UserID).first
#if commend_user.present?
# GxCommendUser.delete_all(user_id: user.UserID)
#unless commend_user.today_changed?
#destroy u's commend_user list
#GxCommendUser.delete_all(user_id: user.UserID)
#update commend_user
#set_commend_users(user.UserID)
#end
#end
GxCommendUser.set_commend_users(user.UserID)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment