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