ish_models 0.0.33.304 → 3.1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +28 -0
  4. data/Rakefile +15 -0
  5. data/app/assets/config/ish_models_manifest.js +1 -0
  6. data/app/assets/stylesheets/ish_models/application.css +15 -0
  7. data/app/controllers/ish_models/application_controller.rb +4 -0
  8. data/app/helpers/ish_models/application_helper.rb +4 -0
  9. data/app/jobs/ish_models/application_job.rb +4 -0
  10. data/app/mailers/ish_models/application_mailer.rb +6 -0
  11. data/app/models/ish_models/application_record.rb +5 -0
  12. data/app/views/layouts/ish_models/application.html.erb +15 -0
  13. data/config/routes.rb +2 -0
  14. data/lib/ish_models/engine.rb +5 -0
  15. data/lib/ish_models/version.rb +3 -0
  16. data/lib/ish_models.rb +4 -89
  17. data/lib/tasks/ish_models_tasks.rake +4 -0
  18. data/lib/{office/admin_message.rb → wco/profile.rb} +2 -5
  19. metadata +32 -221
  20. data/lib/address.rb +0 -20
  21. data/lib/feature.rb +0 -32
  22. data/lib/gallery.rb +0 -66
  23. data/lib/gameui/asset3d.rb +0 -35
  24. data/lib/gameui/map.rb +0 -260
  25. data/lib/gameui/map_bookmark.rb +0 -9
  26. data/lib/gameui/marker.rb +0 -128
  27. data/lib/iro/alert.rb-bk +0 -72
  28. data/lib/ish/cache_key.rb +0 -14
  29. data/lib/ish/configuration.rb +0 -11
  30. data/lib/ish/crawler.rb +0 -26
  31. data/lib/ish/email_campaign.rb +0 -55
  32. data/lib/ish/email_context.rb +0 -113
  33. data/lib/ish/email_template.rb +0 -115
  34. data/lib/ish/email_unsubscribe.rb +0 -19
  35. data/lib/ish/event.rb +0 -20
  36. data/lib/ish/image_asset.rb +0 -38
  37. data/lib/ish/invoice.rb +0 -130
  38. data/lib/ish/lorem_ipsum.rb +0 -30
  39. data/lib/ish/meeting.rb +0 -31
  40. data/lib/ish/payment.rb +0 -29
  41. data/lib/ish/premium_item.rb +0 -13
  42. data/lib/ish/railtie.rb +0 -8
  43. data/lib/ish/user_profile.rb +0 -146
  44. data/lib/ish/utils.rb +0 -45
  45. data/lib/mongoid/votable.rb +0 -247
  46. data/lib/mongoid/voter.rb +0 -96
  47. data/lib/newsitem.rb +0 -94
  48. data/lib/office/action.rb +0 -32
  49. data/lib/office/action_tie.rb +0 -16
  50. data/lib/office/directmail_envelope.rb +0 -51
  51. data/lib/office/email_action.rb +0 -34
  52. data/lib/office/email_action_tie.rb +0 -18
  53. data/lib/office/email_attachment.rb +0 -12
  54. data/lib/office/email_conversation.rb +0 -86
  55. data/lib/office/email_conversation_lead.rb +0 -11
  56. data/lib/office/email_conversation_tag.rb +0 -14
  57. data/lib/office/email_filter.rb +0 -45
  58. data/lib/office/email_message.rb +0 -229
  59. data/lib/office/email_message_stub.rb +0 -22
  60. data/lib/office/lead_action.rb +0 -24
  61. data/lib/office/lead_action_template.rb +0 -47
  62. data/lib/office/obfuscated_redirect.rb +0 -12
  63. data/lib/office/scheduled_email_action.rb +0 -62
  64. data/lib/photo.rb +0 -87
  65. data/lib/report.rb +0 -65
  66. data/lib/video.rb +0 -91
  67. data/lib/wco/appliance.rb +0 -43
  68. data/lib/wco/appliance_tmpl.rb +0 -36
  69. data/lib/wco/leadset.rb +0 -17
  70. data/lib/wco/price.rb +0 -30
  71. data/lib/wco/product.rb +0 -35
  72. data/lib/wco/serverhost.rb +0 -100
  73. data/lib/wco/subscription.rb +0 -25
@@ -1,35 +0,0 @@
1
-
2
- # require 'aws-sdk'
3
- require 'mongoid_paperclip'
4
-
5
- class ::Gameui::Asset3d
6
- include Mongoid::Document
7
- include Mongoid::Timestamps
8
- include Mongoid::Paperclip
9
- include Ish::Utils
10
-
11
- field :filename
12
-
13
- belongs_to :marker, class_name: 'Gameui::Marker', optional: true
14
- belongs_to :invoice, class_name: 'Ish::Invoice', optional: true
15
- belongs_to :email_message, class_name: 'Office::EmailMessage', optional: true, inverse_of: :asset3ds
16
-
17
- has_mongoid_attached_file :object,
18
- :storage => :s3,
19
- :s3_credentials => ::S3_CREDENTIALS,
20
- :path => "assets3d/:id/:filename",
21
- :s3_protocol => 'https',
22
- :validate_media_type => false,
23
- s3_region: ::S3_CREDENTIALS[:region]
24
-
25
- do_not_validate_attachment_file_type :object
26
-
27
- def export_fields
28
- %w|
29
- marker_id invoice_id
30
- asset3d_file_name asset3d_content_type asset3d_file_size asset3d_updated_at asset3d_fingerprint
31
- |;
32
- end
33
-
34
- end
35
- GA3 = ::Gameui::Asset3d
data/lib/gameui/map.rb DELETED
@@ -1,260 +0,0 @@
1
-
2
- require 'ish/premium_item'
3
- require 'ish/utils'
4
-
5
- class ::Gameui::Map
6
- include Mongoid::Document
7
- include Mongoid::Timestamps
8
- include Ish::PremiumItem
9
- include Ish::Utils
10
-
11
- field :name
12
-
13
- field :slug
14
- validates :slug, uniqueness: true, presence: true
15
-
16
- field :description
17
-
18
- ## @TODO: probably, abstract this. _vp_ 2022-09-20
19
- field :deleted_at, type: Time, default: nil
20
-
21
- has_many :markers, :class_name => '::Gameui::Marker', inverse_of: :map
22
- has_many :from_markers, :class_name => '::Gameui::Marker', inverse_of: :destination
23
-
24
- has_many :newsitems, inverse_of: :map, order: :created_at.desc
25
-
26
- # @TODO: remove field, replace with relation. _vp_ 2022-09-13
27
- field :parent_slug
28
- belongs_to :parent, class_name: '::Gameui::Map', inverse_of: :childs, optional: true
29
- has_many :childs, class_name: '::Gameui::Map', inverse_of: :parent
30
-
31
- has_one :image, class_name: '::Ish::ImageAsset', inverse_of: :location
32
- belongs_to :creator_profile, class_name: '::Ish::UserProfile', inverse_of: :my_maps
33
-
34
- has_and_belongs_to_many :bookmarked_profiles, class_name: '::Ish::UserProfile', inverse_of: :bookmarked_location
35
-
36
- # shareable, nonpublic
37
- field :is_public, type: Boolean, default: true
38
- scope :public, ->{ where( is_public: true ) }
39
- has_and_belongs_to_many :shared_profiles, :class_name => 'Ish::UserProfile', :inverse_of => :shared_locations
40
-
41
- field :version, type: String, default: '0.0.0'
42
-
43
- ## @TODO: or self, right? and refactor this, seems N+1. _vp_ 2022-09-13
44
- field :map_slug
45
- def map
46
- ::Gameui::Map.where( slug: map_slug ).first
47
- end
48
-
49
- RATED_OPTIONS = [ 'pg-13', 'r', 'nc-17' ]
50
- field :rated, default: 'pg-13' # 'r', 'nc-17'
51
-
52
- ## Possible keys: description, map, markers, newsitems,
53
- field :labels, type: Object, default: <<~AOL
54
- { "description":"Description", "map":"Map", "markers":"Markers", "newsitems":"Newsitems"
55
- }
56
- AOL
57
-
58
- ## Possible keys:
59
- ## config.description.collapsible
60
- field :config, type: Object, default: <<~AOL
61
- { "map_panel_type": "ThreePanelV1",
62
- "studio": { "hasFloor": true, "studioLength": 2500, "studioWidth": 2500 }
63
- }
64
- AOL
65
-
66
- # @deprecated, dont use!
67
- field :img_path
68
-
69
- ## Not used! See config.map_panel_type instead.
70
- # MAP_TYPES = [ :map_2d, :map_3d, :map_geospatial, :map_gallery, :map_toc ] ## Mostly not implemented. _vp_ 2022-09-06
71
- # field :map_type, default: :map_2d
72
-
73
- ## Make sure to use x,y,z and w,h as appropriate.
74
- ## @TODO: abstract this into a module
75
- field :x, type: Float
76
- field :y, type: Float
77
- field :z, type: Float
78
-
79
- ## Make sure to use x,y,z and w,h as appropriate.
80
- field :w, type: Integer
81
- validates :w, presence: true
82
- field :h, type: Integer
83
- validates :h, presence: true
84
- # @TODO: this is shared between map and marker, move to a concern.
85
- before_validation :compute_w_h
86
- def compute_w_h
87
- return if !image ## @TODO: test this
88
-
89
- begin
90
- geo = Paperclip::Geometry.from_file(Paperclip.io_adapters.for(image.image))
91
- self.w = geo.width
92
- self.h = geo.height
93
- rescue Paperclip::Errors::NotIdentifiedByImageMagickError => e
94
- puts! e, 'Could not #compute_w_h'
95
- # @TODO: do something with this
96
- end
97
- end
98
-
99
- ORDERING_TYPE_ALPHABETIC = 'alphabetic'
100
- ORDERING_TYPE_CUSTOM = 'custom'
101
- ORDERING_TYPE_TIMESTAMP = 'timestamp'
102
- ORDERING_TYPES = [ ORDERING_TYPE_ALPHABETIC, ORDERING_TYPE_CUSTOM, ORDERING_TYPE_TIMESTAMP ]
103
- field :ordering_type, type: String, default: 'custom' # timestamp, alphabetic, custom
104
- validates :ordering_type, presence: true
105
-
106
- def self.list conditions = { is_trash: false }
107
- out = self.order_by( created_at: :desc )
108
- [[nil, nil]] + out.map { |item| [ item.name, item.id.to_s ] }
109
- end
110
-
111
- def breadcrumbs
112
- out = [{ name: self.name, slug: self.slug, link: false }]
113
- p = self.parent
114
- while p
115
- out.push({ name: p.name, slug: p.slug })
116
- p = p.parent
117
- end
118
- out.reverse
119
- end
120
-
121
- ##
122
- ## @TODO: move the export func, below, to a module. _vp_ 2022-09-20
123
- ##
124
-
125
- def empty_export
126
- return {
127
- galleries: {},
128
- image_assets: {},
129
- maps: {}, markers: {},
130
- newsitems: {},
131
- photos: {}, profiles: {},
132
- reports: {},
133
- videos: {},
134
- }
135
- end
136
- def self.empty_export; Gameui::Map.new.empty_export; end
137
-
138
- def empty_export_arr
139
- return {
140
- galleries: [],
141
- image_assets: [],
142
- maps: [], markers: [],
143
- newsitems: [],
144
- photos: [], profiles: [],
145
- reports: [],
146
- videos: [],
147
- }
148
- end
149
-
150
- def export_key_to_class
151
- return {
152
- galleries: 'Gallery',
153
- image_assets: 'Ish::ImageAsset',
154
- maps: 'Gameui::Map',
155
- markers: 'Gameui::Marker',
156
- newsitems: 'Newsitem',
157
- photos: 'Photo',
158
- profiles: 'Ish::UserProfile',
159
- reports: 'Report',
160
- videos: 'Video',
161
- # 'galleries' => 'Gallery',
162
- # 'image_assets' => 'Ish::ImageAsset',
163
- # 'maps' => 'Gameui::Map',
164
- # 'markers' => 'Gameui::Marker',
165
- # 'newsitems' => 'Newsitem',
166
- # 'photos' => 'Photo',
167
- # 'profiles' => 'Ish::UserProfile',
168
- # 'reports' => 'Report',
169
- # 'videos' => 'Video',
170
- }.with_indifferent_access
171
- end
172
- def self.export_key_to_class
173
- Map.new.export_key_to_class
174
- end
175
-
176
- def export_fields
177
- %w|
178
- creator_profile_id config
179
- deleted_at description
180
- h
181
- is_public
182
- labels
183
- map_slug
184
- name
185
- ordering_type
186
- parent_slug
187
- rated
188
- slug
189
- version
190
- w
191
- |
192
- end
193
-
194
- ## This is the starting point _vp_ 2022-03-12
195
- ##
196
- def export_subtree
197
- collected = collect(empty_export)
198
- exportable = empty_export_arr
199
- collected.map do |k, v|
200
- if v.present?
201
- v.map do |id|
202
- id = id[0]
203
- item = export_key_to_class[k].constantize.unscoped.find id
204
- export = item.export
205
- exportable[k].push( export )
206
- end
207
- end
208
- end
209
- JSON.pretty_generate exportable
210
- end
211
-
212
- def collect export_object
213
- map = self
214
- export_object[:maps][map.id.to_s] = map.id.to_s
215
-
216
- if map.markers.present?
217
- map.markers.map do |marker|
218
- id = marker.id.to_s
219
- if !export_object[:markers][id]
220
- marker.collect( export_object )
221
- end
222
- export_object[:markers][id] = id
223
- end
224
- end
225
-
226
- if map.newsitems.present?
227
- map.newsitems.map do |newsitem|
228
- id = newsitem.id.to_s
229
- export_object[:newsitems][id] = id
230
- newsitem.collect export_object
231
- end
232
- end
233
-
234
- ## @TODO: maybe implement this later, maybe not. _vp_ 2022-03-12
235
- # if map.childs.present?
236
- # export_object[:maps].push( map.childs.map &:id )
237
- # map.childs.map do |child|
238
- # child.collect export_object
239
- # end
240
- # end
241
-
242
- if map.creator_profile.present?
243
- export_object[:profiles][map.creator_profile.id.to_s] = map.creator_profile.id.to_s
244
- end
245
-
246
- if map.image.present?
247
- export_object[:image_assets][map.image.id.to_s] = map.image.id.to_s
248
- end
249
-
250
- export_object
251
- end
252
-
253
- ## endExport
254
-
255
- field :newsitems_page_size, default: 25
256
-
257
- end
258
-
259
- Location = ::Gameui::Map
260
- Map = Gameui::Map
@@ -1,9 +0,0 @@
1
-
2
- class ::Gameui::MapBookmark
3
- include Mongoid::Document
4
- include Mongoid::Timestamps
5
-
6
- belongs_to :profile, class_name: 'Ish::UserProfile'
7
- belongs_to :location, class_name: '::Gameui::Map'
8
-
9
- end
data/lib/gameui/marker.rb DELETED
@@ -1,128 +0,0 @@
1
-
2
- class ::Gameui::Marker
3
- include Mongoid::Document
4
- include Mongoid::Timestamps
5
- include Ish::Utils
6
-
7
- field :name, type: String
8
- validates_uniqueness_of :name, scope: :map_id
9
- validates_presence_of :name
10
-
11
- field :ordering, type: String, default: 'jjj'
12
-
13
- ITEM_TYPE_LOCATION = '::Gameui::Map' # @TODO: this used to be gameui-location . How is this different from gameui-map ?
14
- ITEM_TYPE_MAP = 'gameui-map'
15
- ITEM_TYPE_OBJ = 'gameui-obj'
16
- ITEM_TYPES = [ ITEM_TYPE_LOCATION, ITEM_TYPE_MAP, ITEM_TYPE_OBJ ]
17
- field :item_type, type: String
18
- validates :item_type, presence: true
19
-
20
- field :url
21
- field :version, type: String, default: '0.0.0'
22
- field :description
23
-
24
- has_one :image, class_name: '::Ish::ImageAsset', inverse_of: :marker
25
- has_one :title_image, class_name: '::Ish::ImageAsset', inverse_of: :marker_title
26
- has_one :asset3d, class_name: '::Gameui::Asset3d'
27
- def is_3d
28
- !!asset3d
29
- end
30
-
31
- field :deleted_at, type: Time, default: nil # @TODO: replace with paranoia
32
-
33
- ## @TODO: abstract this into a module
34
- field :x, :type => Float, default: 0
35
- field :y, :type => Float, default: 0
36
- field :z, :type => Float, default: 0
37
- field :castShadow, type: Boolean, default: true
38
- field :receiveShadow, type: Boolean, default: false
39
-
40
- field :is_public, type: Boolean, default: true
41
- def self.public
42
- where( is_public: true )
43
- end
44
- ## Active AND [ mine, shared, or public ]
45
- def self.permitted_to profile
46
- active.any_of( {is_public: true},
47
- {:shared_profile_ids => profile.id},
48
- {creator_profile_id: profile.id} )
49
- end
50
-
51
- field :is_active, type: Boolean, default: true
52
- def self.active
53
- where( is_active: true )
54
- end
55
-
56
- has_and_belongs_to_many :shared_profiles, :class_name => 'Ish::UserProfile', :inverse_of => :shared_markers
57
-
58
- belongs_to :map, class_name: '::Gameui::Map', inverse_of: :markers
59
-
60
- belongs_to :destination, class_name: '::Gameui::Map', inverse_of: :from_markers, optional: true
61
-
62
- belongs_to :creator_profile, class_name: 'Ish::UserProfile', inverse_of: :my_markers
63
-
64
- # # @deprecated, don't use!
65
- # # _vp_ 2021-09-23
66
- # field :img_path
67
- # # validates :img_path, presence: true
68
- # field :title_img_path
69
- # # validates :title_img_path, presence: true
70
-
71
- field :w, type: Integer
72
- validates :w, presence: true
73
- field :h, type: Integer
74
- validates :h, presence: true
75
- # @TODO: this is shared between map and marker, move to a concern.
76
- before_validation :compute_w_h
77
- def compute_w_h
78
- if !image # @TODO: think about this
79
- self.h = self.w = 0
80
- return
81
- end
82
- begin
83
- geo = Paperclip::Geometry.from_file(Paperclip.io_adapters.for(image.image))
84
- self.w = geo.width
85
- self.h = geo.height
86
- rescue Paperclip::Errors::NotIdentifiedByImageMagickError => e
87
- puts! e, 'Could not #compute_w_h'
88
- # @TODO: do something with this
89
- end
90
- end
91
-
92
- field :centerOffsetX, type: Float, default: 0
93
- field :centerOffsetY, type: Float, default: 0
94
-
95
-
96
-
97
- def export_fields
98
- %w|
99
- centerOffsetX centerOffsetY creator_profile_id
100
- deleted_at description destination_id
101
- h
102
- is_active is_public item_type
103
- map_id
104
- name
105
- ordering
106
- url
107
- version
108
- w
109
- x
110
- y
111
- |
112
- end
113
-
114
- def collect export_object
115
- if image
116
- export_object[:image_assets][image.id.to_s] = image.id.to_s
117
- end
118
- if title_image
119
- export_object[:image_assets][title_image.id.to_s] = title_image.id.to_s
120
- end
121
- if !export_object[:maps][destination.id.to_s]
122
- destination.collect export_object
123
- end
124
- end
125
-
126
- end
127
-
128
- Marker = Gameui::Marker
data/lib/iro/alert.rb-bk DELETED
@@ -1,72 +0,0 @@
1
-
2
- ##
3
- ## for alerting
4
- ##
5
- class Iro::Alert
6
- include Mongoid::Document
7
- include Mongoid::Timestamps
8
- store_in collection: 'iro_option_watches'
9
-
10
- field :ticker # like NVDA
11
- validates :ticker, presence: true
12
-
13
- field :symbol # like NVDA_021822C230
14
-
15
- KIND_OPTION = 'option'
16
- KIND_STOCK = 'stock'
17
- KIND_GET_CHAINS = 'get-chains'
18
- KINDS = [ KIND_OPTION, KIND_STOCK, KIND_GET_CHAINS ]
19
- field :kind, type: String
20
- validates :kind, presence: true
21
- def self.kinds_list
22
- [ nil, 'option', 'stock' ]
23
- end
24
-
25
- ## Strike isn't the same as price!
26
- field :strike, :type => Float
27
- # validates :strike, presence: true
28
-
29
- ## What is the price of the option at some strike?
30
- field :mark, type: Float
31
- validates :mark, presence: true
32
-
33
- field :contractType
34
- # validates :contractType, presence: true
35
-
36
- field :expirationDate
37
- # validates :expirationDate, presence: true
38
-
39
- NOTIFICATION_TYPES = [ :NONE, :EMAIL, :SMS ]
40
- ACTIONS = NOTIFICATION_TYPES
41
- NOTIFICATION_NONE = :NONE
42
- NOTIFICATION_EMAIL = :EMAIL
43
- NOTIFICATION_SMS = :SMS
44
- field :notification_type, :type => Symbol, :as => :action
45
- def self.actions_list
46
- [nil] + ACTIONS
47
- end
48
-
49
- STATE_ACTIVE = 'active'
50
- STATE_INACTIVE = 'inactive'
51
- STATES = [ STATE_ACTIVE, STATE_INACTIVE ]
52
- field :state, type: String, default: STATE_ACTIVE
53
- validates :state, presence: true
54
- scope :active, ->{ where( state: STATE_ACTIVE ) }
55
- def self.states_list
56
- [ nil, 'active', 'inactive' ]
57
- end
58
-
59
- DIRECTION_ABOVE = :ABOVE
60
- DIRECTION_BELOW = :BELOW
61
- DIRECTIONS = [ :ABOVE, :BELOW ]
62
- field :direction, :type => Symbol
63
- validates :direction, presence: true
64
- def self.directions_list
65
- [nil] + DIRECTIONS
66
- end
67
-
68
- belongs_to :profile, :class_name => 'Ish::UserProfile'
69
- field :email
70
- field :phone
71
-
72
- end
data/lib/ish/cache_key.rb DELETED
@@ -1,14 +0,0 @@
1
-
2
-
3
- class Ish::CacheKey
4
- include ::Mongoid::Document
5
- include ::Mongoid::Timestamps
6
-
7
- field :cities, :type => Time # /api/cities.json
8
- field :feature_cities, :type => Time # /api/cities/features.json
9
-
10
- def self.one
11
- Ish::CacheKey.first || Ish::CacheKey.new
12
- end
13
- end
14
-
@@ -1,11 +0,0 @@
1
-
2
- module Ish
3
- class Configuration
4
- attr_accessor :s3_credentials
5
-
6
- def initialize
7
- # @s3_credentials ||= { :bucket => '' }
8
- end
9
-
10
- end
11
- end
data/lib/ish/crawler.rb DELETED
@@ -1,26 +0,0 @@
1
- module Ish
2
- class Crawler
3
-
4
- def self.google_first_result text
5
- result = HTTParty.get( "https://www.google.com/search?q=#{text}", :verify => false )
6
- r = Nokogiri::HTML(result.body)
7
- website = r.css('cite')[0].text
8
- website = "https://#{website}" unless website[0..3] == 'http'
9
-
10
- begin
11
- r = HTTParty.get( website, :verify => false )
12
- rescue OpenSSL::SSL::SSLError => e
13
- return { :url => website }
14
- end
15
-
16
- return { :url => website, :html => r.body }
17
- end
18
-
19
- def self.look_for_emails text
20
- email_regex = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
21
- result = text.scan( email_regex )
22
- return result.length > 0 ? result.join(',') : nil
23
- end
24
-
25
- end
26
- end
@@ -1,55 +0,0 @@
1
-
2
- ##
3
- ## Sends a campaign.
4
- ## _vp_ 2023-02-02
5
- ##
6
- class Ish::EmailCampaign
7
- include Mongoid::Document
8
- include Mongoid::Timestamps
9
- store_in collection: 'ish_email_campaigns'
10
-
11
- field :slug
12
- validates_uniqueness_of :slug, allow_nil: true
13
-
14
- PAGE_PARAM_NAME = 'email_contexts_page'
15
-
16
- field :from_email
17
- validates_presence_of :from_email
18
-
19
- belongs_to :email_template
20
- def tmpl; email_template; end
21
-
22
- field :subject
23
- field :body
24
-
25
- field :sent_at, type: DateTime
26
- field :send_at, type: DateTime
27
-
28
- has_many :unsubscribes, class_name: '::Ish::EmailUnsubscribe', inverse_of: :campaign
29
-
30
- def campaign_leads
31
- return ::EmailCampaignLead.where( email_campaign_id: self.id.to_s ).includes( :lead )
32
- end
33
-
34
- def leads
35
- ::Lead.joins( :email_campaign_leads ).where( 'email_campaign_leads.email_campaign_id' => self.id.to_s )
36
- end
37
-
38
- ##
39
- ## For tracking
40
- ##
41
- attr_reader :tid
42
-
43
- def do_send
44
- leads.each do |lead|
45
- ctx = Ctx.create!({
46
- email_template: tmpl,
47
- from_email: tmpl.from_email,
48
- lead_id: lead.id,
49
- send_at: Time.now,
50
- subject: tmpl.subject,
51
- })
52
- end
53
- end
54
-
55
- end