Module: Liszt::ClassMethods

Defined in:
lib/liszt.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.extended(base) ⇒ Object



58
59
60
61
62
# File 'lib/liszt.rb', line 58

def self.extended(base)
  class << base
    attr_reader :liszt_sort_by, :liszt_append_new_items
  end
end

Instance Method Details

#initialize_list!(obj = {}, &block) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/liszt.rb', line 64

def initialize_list!(obj={}, &block)
  objects = liszt_relation(obj).to_a

  # If the caller provided a block, or if they passed in a default
  # with the :sort_by option, sort the objects by that block's
  # output before populating the list with their ids. If not, put
  # the objects in descending order by id.
  ids = case
    when block_given?
      objects.sort_by(&block).map(&:id)
    when @liszt_sort_by
      objects.sort_by(&@liszt_sort_by).map(&:id)
    else
      objects.map(&:id).sort.reverse
    end

  ordered_list(obj).clear_and_populate!(ids)
  ids
end

#liszt_key(obj = {}) ⇒ Object (private)

Return the key for the Redis list that includes the given object.



161
162
163
164
165
166
167
# File 'lib/liszt.rb', line 161

def liszt_key(obj={})
  key = "liszt:#{table_name}"
  @liszt_scope.each do |scope|
    key << ":#{scope}:#{obj[scope]}"
  end
  key
end

#liszt_relation(obj = {}) ⇒ Object (private)

Return a relation/scope containing objects eligible to be in the list that includes the given object.



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/liszt.rb', line 171

def liszt_relation(obj={})
  if @liszt_query.nil?
    query = ['1 = 1']

    @liszt_conditions.each do |key, value|
      query.first << " AND (#{table_name}.#{key} "
      if value.nil?
        query.first << "IS NULL)"
      else
        query.first << "= ?)"
        query << value
      end
    end

    @liszt_scope.each do |scope|
      query.first << " AND (#{table_name}.#{scope} = ?)"
    end

    @liszt_query = query
  end

  where(@liszt_query + @liszt_scope.map { |scope| obj[scope] })
end

#meets_list_conditions?(obj = {}) ⇒ Boolean

Returns:

  • (Boolean)


143
144
145
# File 'lib/liszt.rb', line 143

def meets_list_conditions?(obj={})
  @liszt_conditions.all? { |key, value| obj[key] == value }
end

#ordered_list(obj = {}) ⇒ Object



84
85
86
# File 'lib/liszt.rb', line 84

def ordered_list(obj={})
  Liszt::RedisList.new(liszt_key(obj))
end

#ordered_list_ids(obj = {}) ⇒ Object



92
93
94
95
96
97
98
# File 'lib/liszt.rb', line 92

def ordered_list_ids(obj={})
  if ordered_list_initialized?(obj)
    ordered_list(obj).all
  else
    initialize_list!(obj)
  end
end

#ordered_list_initialized?(obj = {}) ⇒ Boolean

Returns:

  • (Boolean)


88
89
90
# File 'lib/liszt.rb', line 88

def ordered_list_initialized?(obj={})
  ordered_list(obj).initialized?
end

#ordered_list_items(obj = {}, opts = {}) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/liszt.rb', line 100

def ordered_list_items(obj={}, opts={})
  force_refresh = opts.delete(:force_refresh) || false
  previously_initialized = ordered_list_initialized?(obj)

  # If the list isn't initialized already, we can trust ordered_list_ids to
  # do the initialization correctly and ignore the force_refresh flag.
  if force_refresh && previously_initialized
    refresh_ordered_list(obj)
  else
    list_ids = ordered_list_ids(obj)
    records  = liszt_relation(obj).to_a
    real_ids = records.map(&:id)

    if real_ids.to_set == list_ids.to_set
      records.sort_by { |obj| list_ids.index(obj.id) }
    else
      refresh_ordered_records obj, list_ids, records, real_ids
    end
  end
end

#refresh_ordered_list(obj = {}) ⇒ Object

Synchronizes the ordered list with the database, returning the relevant records in order.



123
124
125
126
127
128
129
# File 'lib/liszt.rb', line 123

def refresh_ordered_list(obj={})
  list_ids   = ordered_list_ids(obj)
  records    = liszt_relation(obj).to_a
  real_ids   = records.map(&:id)

  refresh_ordered_records obj, list_ids, records, real_ids
end

#refresh_ordered_records(obj, list_ids, records, real_ids) ⇒ Object (private)



149
150
151
152
153
154
155
156
157
158
# File 'lib/liszt.rb', line 149

def refresh_ordered_records(obj, list_ids, records, real_ids)
  merged_ids = Liszt.merge_id_lists(
                 real_ids, list_ids, @liszt_append_new_items)

  if merged_ids != list_ids
    ordered_list(obj).clear_and_populate!(merged_ids)
  end

  records.sort_by { |obj| merged_ids.index(obj.id) }
end

#update_ordered_list(obj, new_ids) ⇒ Object

Update the given object's list with the given ids. Returns the final list of ids, which may be different from the given list if the given list was inconsistent with the database.



134
135
136
137
138
139
140
141
# File 'lib/liszt.rb', line 134

def update_ordered_list(obj, new_ids)
  records    = ordered_list_items(obj, force_refresh: true)
  real_ids   = records.map(&:id)
  merged_ids = Liszt.merge_id_lists(
                 real_ids, new_ids, @liszt_append_new_items)

  ordered_list(obj).clear_and_populate!(merged_ids)
end