Class: Libertree::Model::River

Inherits:
Object
  • Object
show all
Defined in:
lib/libertree/model/river.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.create(*args) ⇒ Object



197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/libertree/model/river.rb', line 197

def self.create(*args)
  n = River.num_appended_to_all
  river = super

  if River.num_appended_to_all != n
    Libertree::Model::Job.create(
      task: 'river:refresh-all',
      params: {
        'account_id' => river.,
      }.to_json
    )
  end

  if ! river.appended_to_all
    Libertree::Model::Job.create(
      task: 'river:refresh',
      params: {
        'river_id' => river.id,
      }.to_json
    )
  end

  river
end

.num_appended_to_allObject



193
194
195
# File 'lib/libertree/model/river.rb', line 193

def self.num_appended_to_all
  self.where(:appended_to_all).count
end

Instance Method Details

#accountObject



4
5
6
# File 'lib/libertree/model/river.rb', line 4

def 
  @account ||= Account[self.]
end

#add_post(post) ⇒ Object



16
17
18
# File 'lib/libertree/model/river.rb', line 16

def add_post( post )
  Libertree::DB.dbh[ "INSERT INTO river_posts ( river_id, post_id ) VALUES ( ?, ? )", self.id, post.id ].get
end

#being_processed?Boolean

Returns:

  • (Boolean)


234
235
236
237
238
239
240
# File 'lib/libertree/model/river.rb', line 234

def being_processed?
  !! Job[
    task: 'river:refresh',
    params: %|{"river_id":#{self.id}}|,
    time_finished: nil
  ]
end

#contains?(post) ⇒ Boolean

Returns:

  • (Boolean)


12
13
14
# File 'lib/libertree/model/river.rb', line 12

def contains?( post )
  Libertree::DB.dbh[ "SELECT river_contains_post(?, ?)", self.id, post.id ].single_value
end

#delete_cascade(force = false) ⇒ Object



181
182
183
184
185
186
187
188
189
190
191
# File 'lib/libertree/model/river.rb', line 181

def delete_cascade(force=false)
  if ! force && self.appended_to_all
    Libertree::Model::Job.create(
      task: 'river:refresh-all',
      params: {
        'account_id' => self.,
      }.to_json
    )
  end
  DB.dbh["SELECT delete_cascade_river(?)", self.id].get
end

#home?Boolean

Returns:

  • (Boolean)


222
223
224
# File 'lib/libertree/model/river.rb', line 222

def home?
  self.home
end

#mark_all_posts_as_readObject



242
243
244
245
246
# File 'lib/libertree/model/river.rb', line 242

def mark_all_posts_as_read
  DB.dbh[ %{SELECT mark_all_posts_in_river_as_read_by(?,?)},
          self.id,
          self..id ].get
end

#matches_post?(post, ignore_keys = []) ⇒ Boolean

Returns:

  • (Boolean)


89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/libertree/model/river.rb', line 89

def matches_post?(post, ignore_keys=[])
  # Negations: Must not satisfy any of the conditions
  # Requirements: Must satisfy every required condition
  # Regular terms: Must satisfy at least one condition

  conditions = {
    negations:    [],
    requirements: [],
    regular:      []
  }

  query = self.parsed_query
  keys = query.keys - ignore_keys
  keys.each do |term|
    test = lambda {|data| term_matches_post?(term, post, data)}
    query[term].keys.each do |group|
      conditions[group] += query[term][group].map(&test)
    end
  end

  conditions[:negations].none? &&
    conditions[:requirements].all? &&
    (conditions[:regular].count > 0 ? conditions[:regular].any? : true)
end

#parsed_query(override_cache = false) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
# File 'lib/libertree/model/river.rb', line 31

def parsed_query(override_cache=false)
  return @parsed_query  if @parsed_query && ! override_cache

  full_query = self.query
  if ! self.appended_to_all
    full_query += ' ' + self..rivers_appended.map(&:query).join(' ')
    full_query.strip!
  end

  @parsed_query = Libertree::Query.new(full_query, self..id, self.id).parsed
end

#posts(opts = {}) ⇒ Object



20
21
22
23
24
25
26
27
28
29
# File 'lib/libertree/model/river.rb', line 20

def posts( opts = {} )
  time = Time.at( opts.fetch(:time, Time.now.to_f) ).strftime("%Y-%m-%d %H:%M:%S.%6N%z")
  Post.s(%{SELECT * FROM posts_in_river(?,?,?,?,?,?)},
         self.id,
         self..id,
         time,
         opts[:newer],
         opts[:order_by] == :comment,
         opts.fetch(:limit, 30))
end

#refresh_posts(n = 512) ⇒ Object



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/libertree/model/river.rb', line 114

def refresh_posts( n = 512 )
  # delete posts early to avoid confusion about posts that don't
  # match the new query
  DB.dbh[ "DELETE FROM river_posts WHERE river_id = ?", self.id ].get

  # TODO: this is slow despite indices.
  #posts = Post.where{|p| ~Sequel.function(:post_hidden_by_account, p.id, account.id)}

  # get posts that are not hidden by account and get cracking
  posts = Post.filter_by_query(self.parsed_query, self., Post.not_hidden_by())

  # get up to n posts
  # this is faster than using find_all on the set
  count = 0
  matching = []
  posts.reverse_order(:id).each do |post|
    break  if count >= n

    if res = self.matches_post?(post, ['flag', 'word', 'phrase', 'tag', 'visibility', 'from', 'via'])
      count += 1
      matching << post
    end
  end

  if matching.any?
    DB.dbh[ "INSERT INTO river_posts SELECT ?, id FROM posts WHERE id IN ?", self.id, matching.map(&:id)].get
  end
end

#revise(params) ⇒ Object

Parameters:

  • params

    Untrusted parameter Hash. Be careful, this input usually comes from the outside world.



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/libertree/model/river.rb', line 144

def revise( params )
  self.label = params['label'].to_s
  self.query = params['query'].to_s

  n = River.num_appended_to_all
  self.appended_to_all = !! params['appended_to_all']
  if River.num_appended_to_all != n || self.appended_to_all
    job_data = {
      task: 'river:refresh-all',
      params: {
        'account_id' => self.,
      }.to_json
    }
    existing_jobs = Job.pending_where(
      %{
        task = ?
        AND params = ?
      },
      job_data[:task],
      job_data[:params]
    )
    if existing_jobs.empty?
      Job.create job_data
    end
  end

  if ! self.appended_to_all
    Libertree::Model::Job.create(
      task: 'river:refresh',
      params: {
        'river_id' => self.id,
      }.to_json
    )
  end
  self.save
end

#should_contain?(post) ⇒ Boolean

Returns:

  • (Boolean)


8
9
10
# File 'lib/libertree/model/river.rb', line 8

def should_contain?( post )
  ! self.contains?(post) && ! post.hidden_by?(self.) && self.matches_post?(post)
end

#term_matches_post?(term, post, data) ⇒ Boolean

Returns:

  • (Boolean)


43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/libertree/model/river.rb', line 43

def term_matches_post?(term, post, data)
  case term
  when 'flag'
    # TODO: most of these are slow
    case data
    when 'forest'
      true  # Every post is a post in the forest.  :forest is sort of a no-op term
    when 'tree'
      post.local?
    when 'unread'
      ! post.read_by?(self.)
    when 'liked'
      post.liked_by? self..member
    when 'commented'
      post.commented_on_by? self..member
    when 'subscribed'
      self..subscribed_to? post
    end
  when 'contact-list'
    data.last.include? post.member_id
  when 'from'
    post.member_id == data
  when 'river'
    data.matches_post?(post)
  when 'visibility'
    post.visibility == data
  when 'word-count'
    case data
    when /^< ?([0-9]+)$/
      n = $1.to_i
      post.text.scan(/\S+/).count < n
    when /^> ?([0-9]+)$/
      n = $1.to_i
      post.text.scan(/\S+/).count > n
    end
  when 'spring'
    data.includes?(post)
  when 'via'
    post.via == data
  when 'tag'
    post.hashtags.include? data
  when 'phrase', 'word'
    /(?:^|\b|\s)#{Regexp.escape(data)}(?:\b|\s|$)/i === post.text
  end
end

#to_hashObject



226
227
228
229
230
231
232
# File 'lib/libertree/model/river.rb', line 226

def to_hash
  {
    'id'    => self.id,
    'label' => self.label,
    'query' => self.query,
  }
end