<commit_before>#
#
# Everything to do with user <> user relationships should be here.
#
# "relationships" is the join table:
#    user has many users through relationships
#
module UserExtension::Users

  def self.included(base)

    base.send :include, InstanceMethods

    base.instance_eval do
      serialize_as IntArray, :friend_id_cache, :foe_id_cache

      initialized_by :update_contacts_cache,
        :friend_id_cache, :foe_id_cache

      ##
      ## PEERS
      ##

      # (peer_id_cache defined in UserExtension::Organize)
      has_many :peers, :class_name => 'User',
        :finder_sql => 'SELECT users.* FROM users WHERE users.id IN (#{peer_id_cache.to_sql})' do
        # will_paginate bug: Association with finder_sql raises TypeError
        #  http://sod.lighthouseapp.com/projects/17958/tickets/120-paginate-association-with-finder_sql-raises-typeerror#ticket-120-5
        def find(*args)
          options = args.extract_options!
          sql = @finder_sql

          sql += " ORDER BY " + sanitize_sql(options[:order]) if options[:order]
          sql += sanitize_sql [" LIMIT ?", options[:limit]] if options[:limit]
          sql += sanitize_sql [" OFFSET ?", options[:offset]] if options[:offset]

          User.find_by_sql(sql)
        end
      end

      # same as results as user.peers, but chainable with other named scopes
      scope(:peers_of, lambda do |user|
        {:conditions => ['users.id in (?)', user.peer_id_cache]}
      end)

      ##
      ## USER'S STATUS / PUBLIC WALL
      ##

      has_one :wall_discussion, :as => :commentable, :dependent => :destroy, :class_name => "Discussion"

      before_destroy :save_relationships
      attr_reader :peers_before_destroy, :contacts_before_destroy

      ##
      ## RELATIONSHIPS
      ##

      has_many :relationships, :dependent => :destroy do
        def with(user) find_by_contact_id(user.id) end
      end

      has_many :discussions, :through => :relationships, :order => 'discussions.replied_at DESC'
      has_many :contacts,    :through => :relationships

      has_many :friends, :through => :relationships, :conditions => "relationships.type = 'Friendship'", :source => :contact do
        def most_active(options = {})
          options[:limit] ||= 13
          max_visit_count = find(:first, :select => 'MAX(relationships.total_visits) as id').id || 1
          select = "users.*, " + quote_sql([MOST_ACTIVE_SELECT, 2.week.ago.to_i, 2.week.seconds.to_i, max_visit_count])
          find(:all, :limit => options[:limit], :select => select, :order => 'last_visit_weight + total_visits_weight DESC')
        end
      end

      # same result as user.friends, but chainable with other named scopes
      scope(:friends_of, lambda do |user|
        {:conditions => ['users.id in (?)', user.friend_id_cache]}
      end)

      scope(:friends_or_peers_of, lambda do |user|
        {:conditions => ['users.id in (?)', user.friend_id_cache + user.peer_id_cache]}
      end)

      # neither friends nor peers
      # used for autocomplete when we preloaded the friends and peers
      scope(:strangers_to, lambda do |user|
        {:conditions => ['users.id NOT IN (?)',
          user.friend_id_cache + user.peer_id_cache + [user.id]]}
      end)

      ##
      ## CACHE
      ##

      serialize_as IntArray, :friend_id_cache, :foe_id_cache, :peer_id_cache
      initialized_by :update_contacts_cache, :friend_id_cache, :foe_id_cache
      initialized_by :update_membership_cache, :peer_id_cache

      # this seems to be the only way to override the A/R created methods.
      # new accessor defined in user_extension/cache.rb
      remove_method :friend_ids
      #remove_method :foe_ids
      remove_method :peer_ids
    end
  end

  module InstanceMethods

    ##<commit_msg>use User.peer_of(self) instead of has_many :peers with :finder_sql<commit_after>#
#
# Everything to do with user <> user relationships should be here.
#
# "relationships" is the join table:
#    user has many users through relationships
#
module UserExtension::Users

  def self.included(base)

    base.send :include, InstanceMethods

    base.instance_eval do
      serialize_as IntArray, :friend_id_cache, :foe_id_cache

      initialized_by :update_contacts_cache,
        :friend_id_cache, :foe_id_cache

      ##
      ## PEERS
      ##

      # same as results as user.peers, but chainable with other named scopes
      scope(:peers_of, lambda do |user|
        {:conditions => ['users.id in (?)', user.peer_id_cache]}
      end)

      ##
      ## USER'S STATUS / PUBLIC WALL
      ##

      has_one :wall_discussion, :as => :commentable, :dependent => :destroy, :class_name => "Discussion"

      before_destroy :save_relationships
      attr_reader :peers_before_destroy, :contacts_before_destroy

      ##
      ## RELATIONSHIPS
      ##

      has_many :relationships, :dependent => :destroy do
        def with(user) find_by_contact_id(user.id) end
      end

      has_many :discussions, :through => :relationships, :order => 'discussions.replied_at DESC'
      has_many :contacts,    :through => :relationships

      has_many :friends, :through => :relationships, :conditions => "relationships.type = 'Friendship'", :source => :contact do
        def most_active(options = {})
          options[:limit] ||= 13
          max_visit_count = find(:first, :select => 'MAX(relationships.total_visits) as id').id || 1
          select = "users.*, " + quote_sql([MOST_ACTIVE_SELECT, 2.week.ago.to_i, 2.week.seconds.to_i, max_visit_count])
          find(:all, :limit => options[:limit], :select => select, :order => 'last_visit_weight + total_visits_weight DESC')
        end
      end

      # same result as user.friends, but chainable with other named scopes
      scope(:friends_of, lambda do |user|
        {:conditions => ['users.id in (?)', user.friend_id_cache]}
      end)

      scope(:friends_or_peers_of, lambda do |user|
        {:conditions => ['users.id in (?)', user.friend_id_cache + user.peer_id_cache]}
      end)

      # neither friends nor peers
      # used for autocomplete when we preloaded the friends and peers
      scope(:strangers_to, lambda do |user|
        {:conditions => ['users.id NOT IN (?)',
          user.friend_id_cache + user.peer_id_cache + [user.id]]}
      end)

      ##
      ## CACHE
      ##

      serialize_as IntArray, :friend_id_cache, :foe_id_cache, :peer_id_cache
      initialized_by :update_contacts_cache, :friend_id_cache, :foe_id_cache
      initialized_by :update_membership_cache, :peer_id_cache

      # this seems to be the only way to override the A/R created methods.
      # new accessor defined in user_extension/cache.rb
      remove_method :friend_ids
      #remove_method :foe_ids
      #remove_method :peer_ids
    end
  end

  module InstanceMethods

    def peers
      self.class.peers_of(self)
    end

    ##
{'fraction_non_alphanumeric': 0.11073971806423485, 'fraction_numerical': 0.003197209707891295, 'mean_word_length': 2.9529006318207927, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2628008', 'n_tokens_mistral': 2212, 'n_tokens_neox': 2113, 'n_words': 530}