Class: Statesman::Adapters::MongoidQueries::QueryBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/statesman/adapters/mongoid_queries.rb

Instance Method Summary collapse

Constructor Details

#initialize(model, transition_class:, initial_state:, most_recent_transition_alias: nil, transition_name: nil) ⇒ QueryBuilder

Returns a new instance of QueryBuilder.



93
94
95
96
97
98
99
100
101
# File 'lib/statesman/adapters/mongoid_queries.rb', line 93

def initialize(model, transition_class:, initial_state:,
               most_recent_transition_alias: nil,
               transition_name: nil)
  @model = model
  @transition_class = transition_class
  @initial_state = initial_state
  @most_recent_transition_alias = most_recent_transition_alias
  @transition_name = transition_name
end

Instance Method Details

#aggregate_ids_for_all_state(states) ⇒ Object



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/statesman/adapters/mongoid_queries.rb', line 125

def aggregate_ids_for_all_state(states)
  aggregation = [
    # Group by foreign key
    {
      '$group': {
        _id: "$#{model_foreign_key}",
        model_foreign_key => { '$first': "$#{model_foreign_key}" },
      },
    },
    # Trim response to only the foreign key
    { '$project': { _id: 0 } },
  ]

  # Hit the database and return a flat array of ids
  transition_class.collection.aggregate(aggregation).pluck(model_foreign_key)
end

#aggregate_ids_for_most_recent(states, inclusive_match: true) ⇒ Object



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/statesman/adapters/mongoid_queries.rb', line 142

def aggregate_ids_for_most_recent(states, inclusive_match: true)
  aggregation = [
    # Sort most recent
    { '$sort': { sort_key: -1 } },
    # Group by foreign key & get most recent states
    {
      '$group': {
        _id: "$#{model_foreign_key}",
        to_state: { '$first': '$to_state' },
        model_foreign_key => { '$first': "$#{model_foreign_key}" },
      },
    },
    # Include/exclude states by provided states
    { '$match': { to_state: { (inclusive_match ? '$in' : '$nin') => states } } },
    # Trim response to only the foreign key
    { '$project': { _id: 0, to_state: 0 } },
  ]

  # Hit the database and return a flat array of ids
  transition_class.collection.aggregate(aggregation).pluck(model_foreign_key)
end

#states_where(states) ⇒ Object



103
104
105
106
107
108
109
110
111
112
# File 'lib/statesman/adapters/mongoid_queries.rb', line 103

def states_where(states)
  ids = aggregate_ids_for_most_recent(states, inclusive_match: true)

  if initial_state.to_s.in?(states.map(&:to_s))
    all_ids = aggregate_ids_for_all_state(states)
    ids += model.where(_id: { '$nin' => all_ids }).pluck(:id)
  end

  model.where(_id: { '$in' => ids })
end

#states_where_not(states) ⇒ Object



114
115
116
117
118
119
120
121
122
123
# File 'lib/statesman/adapters/mongoid_queries.rb', line 114

def states_where_not(states)
  ids = aggregate_ids_for_most_recent(states, inclusive_match: false)

  unless initial_state.to_s.in?(states.map(&:to_s))
    all_ids = aggregate_ids_for_all_state(states)
    ids += model.where(_id: { '$nin' => all_ids }).pluck(:id)
  end

  model.where(_id: { '$in' => ids })
end