<commit_before>class Opinion < ActiveRecord::Base
  belongs_to :user
  belongs_to :proposal, :touch => true 
  has_many :inclusions
  has_many :points
  has_many :point_listings
  has_many :comments, :as => :commentable, :dependent => :destroy
  
  # has_paper_trail

  include Trackable, Followable, Commentable

  acts_as_tenant(:account)

  _public_fields = 

  scope :published, -> {where( :published => true )}
  scope :public_fields, -> {select( [:long_id, :created_at, :updated_at, :id, :proposal_id, :stance, :stance_segment, :user_id, :explanation, :point_inclusions, :published] )}

  before_save do 
    self.explanation = self.explanation.sanitize if self.explanation
    self.stance_segment = Opinion.get_segment(self.stance)
  end 

  def as_json(options={})
    pubs = ['long_id', 'created_at', 'updated_at', 'id', 'point_inclusions',
            'proposal_id', 'stance', 'stance_segment', 'user_id', 'explanation',
            'published']

    result = super(options)
    result = result.select{|k,v| pubs.include? k}

    make_key(result, 'opinion')
    stubify_field(result, 'user')
    stubify_field(result, 'proposal')
    result['point_inclusions'] = JSON.parse (result['point_inclusions'] || '[]')
    result['point_inclusions'].map! {|p| "/point/#{p}"}
    result.delete('long_id')
    result
  end

  def self.get_or_make(proposal, user, tenant)
    # Each (user,proposal) should have only one opinion.

    if not user
      raise "Need a user to get their opinion!"
    end
    
    # First try to find a published opinion for this user
    your_opinion = Opinion.where(:proposal_id => proposal.id, 
                                 :user => user)
    if your_opinion.length > 1
      raise "Duplicate opinions for user #{user}: #{your_opinion.map {|o| o.id} }!"
    end
    your_opinion = your_opinion.first

    # Otherwise create one
    if not your_opinion
      your_opinion = Opinion.create(:proposal_id => proposal.id,
                                    :user => user ? user : nil,
                                    :long_id => proposal.long_id,
                                    :account_id => tenant.id,
                                    :published => false,
                                    :stance => 0,
                                    :point_inclusions => '[]',
                                    :explanation => ''
                                   )
    end
    your_opinion
  end
    
  def include(point, tenant)
    point_id = (point.is_a?(Point) && point.id) || point

    if Inclusion.where( :point_id => point_id, :user_id => self.user_id ).count !=0
      raise 'Including a point twice!'
    end
    
    attrs = { 
      :point_id => point_id,
      :user_id => self.user_id,
      :opinion_id => self.id,
      :proposal_id => self.proposal_id,
      :account_id => tenant.id
    }
          
    Inclusion.create! ActionController::Parameters.new(attrs).permit!
    self.recache()
  end    
  def absorb( opinion )
    puts("Absorbing opinion #{opinion.id} into #{self.id}")
    # Change the absorbed's everythings to point at this opinion
    opinion.point_listings.update_all({:user_id => user_id, :opinion_id => id})
    opinion.points.update_all(        {:user_id => user_id, :opinion_id => id})
    opinion.inclusions.update_all(    {:user_id => user_id, :opinion_id => id})
    opinion.comments.update_all({:commentable_id => id})
    self.published = self.published or opinion.published
    self.recache()
    opinion.delete()
  end

  def recache<commit_msg>destroy, not delete<commit_after>class Opinion < ActiveRecord::Base
  belongs_to :user
  belongs_to :proposal, :touch => true 
  has_many :inclusions
  has_many :points
  has_many :point_listings
  has_many :comments, :as => :commentable, :dependent => :destroy
  
  # has_paper_trail

  include Trackable, Followable, Commentable

  acts_as_tenant(:account)

  scope :published, -> {where( :published => true )}
  scope :public_fields, -> {select( [:long_id, :created_at, :updated_at, :id, :proposal_id, :stance, :stance_segment, :user_id, :explanation, :point_inclusions, :published] )}

  before_save do 
    self.explanation = self.explanation.sanitize if self.explanation
    self.stance_segment = Opinion.get_segment(self.stance)
  end 

  def as_json(options={})
    pubs = ['long_id', 'created_at', 'updated_at', 'id', 'point_inclusions',
            'proposal_id', 'stance', 'stance_segment', 'user_id', 'explanation',
            'published']

    result = super(options)
    result = result.select{|k,v| pubs.include? k}

    make_key(result, 'opinion')
    stubify_field(result, 'user')
    stubify_field(result, 'proposal')
    result['point_inclusions'] = JSON.parse (result['point_inclusions'] || '[]')
    result['point_inclusions'].map! {|p| "/point/#{p}"}
    result.delete('long_id')
    result
  end

  def self.get_or_make(proposal, user, tenant)
    # Each (user,proposal) should have only one opinion.

    if not user
      raise "Need a user to get their opinion!"
    end
    
    # First try to find a published opinion for this user
    your_opinion = Opinion.where(:proposal_id => proposal.id, 
                                 :user => user)
    if your_opinion.length > 1
      raise "Duplicate opinions for user #{user}: #{your_opinion.map {|o| o.id} }!"
    end
    your_opinion = your_opinion.first

    # Otherwise create one
    if not your_opinion
      your_opinion = Opinion.create(:proposal_id => proposal.id,
                                    :user => user ? user : nil,
                                    :long_id => proposal.long_id,
                                    :account_id => tenant.id,
                                    :published => false,
                                    :stance => 0,
                                    :point_inclusions => '[]',
                                    :explanation => ''
                                   )
    end
    your_opinion
  end
    
  def include(point, tenant)
    point_id = (point.is_a?(Point) && point.id) || point

    if Inclusion.where( :point_id => point_id, :user_id => self.user_id ).count !=0
      raise 'Including a point twice!'
    end
    
    attrs = { 
      :point_id => point_id,
      :user_id => self.user_id,
      :opinion_id => self.id,
      :proposal_id => self.proposal_id,
      :account_id => tenant.id
    }
          
    Inclusion.create! ActionController::Parameters.new(attrs).permit!
    self.recache()
  end    
  def absorb( opinion )
    puts("Absorbing opinion #{opinion.id} into #{self.id}")
    # Change the absorbed's everythings to point at this opinion
    opinion.point_listings.update_all({:user_id => user_id, :opinion_id => id})
    opinion.points.update_all(        {:user_id => user_id, :opinion_id => id})
    opinion.inclusions.update_all(    {:user_id => user_id, :opinion_id => id})
    opinion.comments.update_all({:commentable_id => id})
    self.published = self.published or opinion.published
    self.recache()
    opinion.destroy()
  end

  def recache
{'fraction_non_alphanumeric': 0.12191664303941026, 'fraction_numerical': 0.0008505812305075135, 'mean_word_length': 2.416464891041162, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 65, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 18, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '629869', 'n_tokens_mistral': 2279, 'n_tokens_neox': 2148, 'n_words': 496}