Class: MailyHerald::Context

Inherits:
Object
  • Object
show all
Defined in:
lib/maily_herald/context.rb

Overview

Abstraction layer for accessing collections of Entities and their attributes. Information provided by scope is used while sending mailings.

Context defines following:

  • Entity scope - ActiveRecord::Relation, list of Entities that will be returned by Context.

  • Entity model name - deducted automatically from scope.

  • Entity attributes - Defined as procs that can be evaluated for every item of the scope (single Entity).

  • Entity email - defined as proc or string/symbol (email method name).

Defined Under Namespace

Classes: Attributes, Drop

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name) ⇒ Context

Creates MailyHerald::Context and sets its name.



99
100
101
# File 'lib/maily_herald/context.rb', line 99

def initialize name
  @name = name
end

Instance Attribute Details

#destination(&block) ⇒ Object

Entity email address.

Can be eitner Proc or attribute name (string, symbol).

If block passed, it is saved as destination proc. Block has to:

  • accept single Entity object,

  • return Entity email.

If no block given, destination attribute is returned (a string, symbol or proc).



132
133
134
135
136
137
138
# File 'lib/maily_herald/context.rb', line 132

def destination &block
  if block_given?
    @destination = block
  else
    @destination
  end
end

#nameObject (readonly)

Identification name of the MailyHerald::Context.

This can be then used in MailyHerald.context method to fetch the MailyHerald::Context.



94
95
96
# File 'lib/maily_herald/context.rb', line 94

def name
  @name
end

#titleObject

Friendly name of the MailyHerald::Context.

Displayed ie. in the Web UI.



87
88
89
# File 'lib/maily_herald/context.rb', line 87

def title
  @title
end

Instance Method Details

#attributes(&block) ⇒ Object

Sepcify or return MailyHerald::Context attributes.

Defines Entity attributes that can be accessed using this Context. Attributes defined this way are then accesible in Liquid templates in Generic Mailer (Mailer#generic).

If block passed, it is used to create Context Attributes.

If no block given, current attributes are returned.



202
203
204
205
206
207
208
# File 'lib/maily_herald/context.rb', line 202

def attributes &block
  if block_given?
    @attributes = Attributes.new block
  else
    @attributes
  end
end

#attributes_listObject

Obtains MailyHerald::Context attributes in a form of (nested) Hash which values are procs each returning single Entity attribute value.



212
213
214
215
216
217
218
# File 'lib/maily_herald/context.rb', line 212

def attributes_list
  return {} unless @attributes

  attributes = @attributes.dup
  attributes.setup 
  attributes.for_drop
end

#destination_attributeObject

Returns Entity email attribute name only if it is not defined as a proc.



141
142
143
# File 'lib/maily_herald/context.rb', line 141

def destination_attribute
  @destination unless @destination.respond_to?(:call)
end

#destination_for(entity) ⇒ Object

Fetches Entity’s email address based on MailyHerald::Context destination definition.



146
147
148
# File 'lib/maily_herald/context.rb', line 146

def destination_for entity
  destination_attribute ? entity.send(@destination) : @destination.call(entity)
end

#drop_for(entity, subscription) ⇒ Object

Returns Liquid drop created from Context attributes.



221
222
223
224
225
226
227
# File 'lib/maily_herald/context.rb', line 221

def drop_for entity, subscription
  return {} unless @attributes

  attributes = @attributes.dup
  attributes.setup entity, subscription
  Drop.new(attributes.for_drop)
end

#modelObject

Fetches the Entity model class based on scope.



118
119
120
# File 'lib/maily_herald/context.rb', line 118

def model
  @model ||= @scope.call.klass
end

#scope(&block) ⇒ Object

Defines or returns Entity scope - collection of Entities.

If block passed, it is saved as scope proc. Block has to return ActiveRecord::Relation containing entity objects that will belong to scope.

If no block given, scope proc is called and entity collection returned.



109
110
111
112
113
114
115
# File 'lib/maily_herald/context.rb', line 109

def scope &block
  if block_given?
    @scope = block
  else
    @scope.call
  end
end

#scope_like(query) ⇒ ActiveRecord::Relation

Simply filter Entity scope by email.

If destination is provided in form of Entity attribute name (not the proc), this method creates the scope filtered by ‘query` email using SQL LIKE.

Parameters:

  • query (String)

    email address which is being searched.

Returns:

  • (ActiveRecord::Relation)

    collection filtered by email address



157
158
159
160
161
# File 'lib/maily_herald/context.rb', line 157

def scope_like query
  if destination_attribute
    scope.where("#{model.table_name}.#{destination_attribute} LIKE (?)", "%#{query}%")
  end
end

#scope_with_subscription(list, mode = :inner) ⇒ Object

Returns Entity collection scope with joined Subscription.

Parameters:

  • list (List, Fixnum, String)

    List reference

  • mode (:inner, :outer) (defaults to: :inner)

    SQL JOIN mode



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/maily_herald/context.rb', line 167

def scope_with_subscription list, mode = :inner
  list_id = case list
            when List
              list.id
            when Fixnum
              list
            when String
              list.to_i
            else
              raise ArgumentError
            end

  join_mode = case mode
              when :outer
                "LEFT OUTER JOIN"
              else
                "INNER JOIN"
              end

  subscription_fields_select = Subscription.columns.collect{|c| "#{Subscription.table_name}.#{c.name} AS maily_subscription_#{c.name}"}.join(", ")

  scope.select("#{model.table_name}.*, #{subscription_fields_select}").joins(
    "#{join_mode} #{Subscription.table_name} ON #{Subscription.table_name}.entity_id = #{model.table_name}.id AND #{Subscription.table_name}.entity_type = '#{model.base_class.to_s}' AND #{Subscription.table_name}.list_id = '#{list_id}'"
  )
end