glengarry 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +60 -0
  3. data/Rakefile +12 -0
  4. data/app/assets/images/glengarry/bg.png +0 -0
  5. data/app/assets/javascripts/glengarry/application.js +15 -0
  6. data/app/assets/javascripts/glengarry/dashboard.js +2 -0
  7. data/app/assets/javascripts/glengarry/email_leads.js +2 -0
  8. data/app/assets/stylesheets/glengarry/application.css +13 -0
  9. data/app/assets/stylesheets/glengarry/dashboard.css +4 -0
  10. data/app/assets/stylesheets/glengarry/email_leads.css.erb +147 -0
  11. data/app/assets/stylesheets/scaffold.css +56 -0
  12. data/app/controllers/glengarry/application_controller.rb +12 -0
  13. data/app/controllers/glengarry/email_leads_controller.rb +78 -0
  14. data/app/helpers/glengarry/application_helper.rb +10 -0
  15. data/app/helpers/glengarry/dashboard_helper.rb +4 -0
  16. data/app/helpers/glengarry/email_leads_helper.rb +4 -0
  17. data/app/models/glengarry/email_lead.rb +34 -0
  18. data/app/views/glengarry/email_leads/_form.html.erb +45 -0
  19. data/app/views/glengarry/email_leads/edit.html.erb +6 -0
  20. data/app/views/glengarry/email_leads/index.html.erb +39 -0
  21. data/app/views/glengarry/email_leads/new.html.erb +5 -0
  22. data/app/views/glengarry/email_leads/show.html.erb +40 -0
  23. data/app/views/layouts/glengarry/application.html.erb +21 -0
  24. data/config/routes.rb +4 -0
  25. data/db/migrate/20120804175235_create_glengarry_email_leads.rb +15 -0
  26. data/lib/email_validator.rb +36 -0
  27. data/lib/glengarry/engine.rb +12 -0
  28. data/lib/glengarry/version.rb +3 -0
  29. data/lib/glengarry.rb +4 -0
  30. data/lib/tasks/glengarry_tasks.rake +0 -0
  31. metadata +193 -0
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2012 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,60 @@
1
+ ![Glengarry](http://f.cl.ly/items/3X0b2u0Z2F2d3E1A3q0v/Screen%20Shot%202012-09-04%20at%202.50.35%20PM.png)
2
+
3
+ ## Glengarry
4
+
5
+ Glengarry is a Rails 3.2 engine that allows you to collect and provides an interface for collecting email leads, CAUSE YOU SHOULD ALWAYS BE CLOSIN'. It's a hack that I wrote quickly to give me what I
6
+ needed - it may do the same for you, but I make no representations to its quality or completeness.
7
+
8
+ The email address, IP Address submitting the email address, and reverse geo-coded latitude, longitude, city and country are stored and presented to you in this lovely UI:
9
+ ![UI](http://f.cl.ly/items/2p2y0L3g3V0B1S0h1A37/Screen%20Shot%202012-09-04%20at%203.45.21%20PM.png)
10
+
11
+ You can also download all of the captured emails as a CSV file. JOY.
12
+
13
+ ## Installation
14
+
15
+ Add the gem to your gemfile as follows:
16
+
17
+ gem 'glengarry'
18
+
19
+ Then run ```bundle install```. Now install the migrations:
20
+
21
+ bundle exec glengarry:install:migrations
22
+
23
+ Now simply mount the engine at the path of your choice in your ```config\routes.rb``` file as follows:
24
+
25
+ mount Glengarry::Engine => "/glengarry"
26
+
27
+ ## Using Glengarry in you App
28
+
29
+ Just make a simple form like so:
30
+
31
+ = form_for(Glengarry::EmailLead.new, :url=>glengarry.email_leads_path) do |f|
32
+ - if flash[:notice].present?
33
+ = content_tag :div, flash[:notice], :id => "flash_notice" if flash[:notice].is_a?(String)
34
+ = f.text_field :email
35
+ = f.submit "Submit"
36
+
37
+ After ```POST```ing to the Engine's path, a redirect is issued back to the location the ```POST``` came from. You probably want to use an ```AJAX``` request anyway.
38
+
39
+ ## Lockin' that down
40
+
41
+ You can add basic HTTP authentication by creating an initializer in your ```config``` directory like so:
42
+
43
+ Glengarry::ApplicationController.authenticator = proc {
44
+ authenticate_or_request_with_http_basic 'Glengarry' do |user_name, password|
45
+ user_name == 'username' && password == 'password'
46
+ end
47
+ }
48
+
49
+ ## Specs
50
+
51
+ You'll have to use the dummy application under spec/dummy to first create the test database. Then simply do the usual:
52
+
53
+ bundle exec rake spec
54
+
55
+ ## Complainin', bro?
56
+
57
+ You can get me on Twitter as @MrMcDowall or on App.net as @jmd - have at it, hopefully I'll see you at the Country Club.
58
+
59
+ ## License
60
+ It's all MIT License. Do what you want, check the MIT-LICENSE file, and I'm not responsible for anything you do with it. Bon appetit.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ require 'rails/all'
5
+ rescue LoadError
6
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
+ end
8
+
9
+
10
+ task :default => :spec
11
+
12
+ Bundler::GemHelper.install_tasks
Binary file
@@ -0,0 +1,15 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // the compiled file.
9
+ //
10
+ // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
11
+ // GO AFTER THE REQUIRES BELOW.
12
+ //
13
+ //= require jquery
14
+ //= require jquery_ujs
15
+ //= require_tree .
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,13 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+ *= require_self
12
+ *= require_tree .
13
+ */
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -0,0 +1,147 @@
1
+ body {
2
+ background: url("<%= asset_path('glengarry/bg.png') %>");
3
+ font-family: "PT Sans Narrow", "Verdana";
4
+ font-weight: 400;
5
+ padding: 0;
6
+ margin: 0;
7
+ letter-spacing: .03em;
8
+ line-height: 1.5;
9
+ }
10
+
11
+ header {
12
+ background: #FFF;
13
+ height: 120px;
14
+ padding: 0;
15
+ margin: 0 0 1em 0;
16
+ }
17
+
18
+ h1 {
19
+ width: 800px;
20
+ height: 120px;
21
+ padding-top: 30px;
22
+ text-align: right;
23
+ margin: 0px auto;
24
+ }
25
+
26
+ h1 small {
27
+ display: block;
28
+ font-size: 12px;
29
+ font-weight: 100;
30
+ font-family: helvetica, sans-serif;
31
+ }
32
+
33
+ #page {
34
+ width: 800px;
35
+ margin: 0px auto;
36
+ }
37
+
38
+ #page h1 {
39
+ width: 100%;
40
+ text-align: center;
41
+ }
42
+
43
+ table {
44
+ border: 1px solid #DFDFDF;
45
+ background-color: #F9F9F9;
46
+ width: 100%;
47
+ margin-top: 1.6em;
48
+ -moz-border-radius: 3px;
49
+ -webkit-border-radius: 3px;
50
+ border-radius: 3px;
51
+ font-family: Arial,"Bitstream Vera Sans",Helvetica,Verdana,sans-serif;
52
+ color: #333;
53
+ margin-bottom: 2em;
54
+ }
55
+ table td, table th {
56
+ border-top-color: white;
57
+ border-bottom: 1px solid #DFDFDF;
58
+ color: #555;
59
+ }
60
+ table th {
61
+ text-shadow: rgba(255, 255, 255, 0.796875) 0px 1px 0px;
62
+ font-family: Georgia,"Times New Roman","Bitstream Charter",Times,serif;
63
+ font-weight: normal;
64
+ padding: 7px 7px 8px;
65
+ text-align: left;
66
+ line-height: 1.3em;
67
+ font-size: 14px;
68
+ height: 50px;
69
+ }
70
+
71
+ table tr {
72
+ height: 3em;
73
+ }
74
+
75
+ table td {
76
+ font-size: 12px;
77
+ padding: 4px 7px 2px;
78
+ vertical-align: top;
79
+ }
80
+
81
+ .pagination {
82
+ text-align: center;
83
+ padding: 1em 0 0 0 ;
84
+ }
85
+
86
+ .pagination .page, .first, .prev, .next, .last {
87
+ width: 32px;
88
+ height: 32px;
89
+ display: inline-block;
90
+ }
91
+
92
+ .pagination .first, .last {
93
+ width: 64px;
94
+ }
95
+
96
+ /* cupid blue (inspired by okcupid.com)
97
+ *******************************************************************************/
98
+ button {
99
+ float: right;
100
+ background-color: #d7e5f5;
101
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #d7e5f5), color-stop(100%, #cbe0f5));
102
+ background-image: -webkit-linear-gradient(top, #d7e5f5, #cbe0f5);
103
+ background-image: -moz-linear-gradient(top, #d7e5f5, #cbe0f5);
104
+ background-image: -ms-linear-gradient(top, #d7e5f5, #cbe0f5);
105
+ background-image: -o-linear-gradient(top, #d7e5f5, #cbe0f5);
106
+ background-image: linear-gradient(top, #d7e5f5, #cbe0f5);
107
+ border-top: 1px solid #abbbcc;
108
+ border-left: 1px solid #a7b6c7;
109
+ border-bottom: 1px solid #a1afbf;
110
+ border-right: 1px solid #a7b6c7;
111
+ -webkit-border-radius: 12px;
112
+ -moz-border-radius: 12px;
113
+ border-radius: 12px;
114
+ -webkit-box-shadow: inset 0 1px 0 0 white;
115
+ -moz-box-shadow: inset 0 1px 0 0 white;
116
+ box-shadow: inset 0 1px 0 0 white;
117
+ color: #1a3e66;
118
+ font: normal 11px "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif;
119
+ line-height: 1;
120
+ padding: 6px 0 7px 0;
121
+ text-align: center;
122
+ text-shadow: 0 1px 1px #fff;
123
+ width: 150px; }
124
+ button:hover {
125
+ background-color: #ccd9e8;
126
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ccd9e8), color-stop(100%, #c1d4e8));
127
+ background-image: -webkit-linear-gradient(top, #ccd9e8, #c1d4e8);
128
+ background-image: -moz-linear-gradient(top, #ccd9e8, #c1d4e8);
129
+ background-image: -ms-linear-gradient(top, #ccd9e8, #c1d4e8);
130
+ background-image: -o-linear-gradient(top, #ccd9e8, #c1d4e8);
131
+ background-image: linear-gradient(top, #ccd9e8, #c1d4e8);
132
+ border-top: 1px solid #a1afbf;
133
+ border-left: 1px solid #9caaba;
134
+ border-bottom: 1px solid #96a3b3;
135
+ border-right: 1px solid #9caaba;
136
+ -webkit-box-shadow: inset 0 1px 0 0 #f2f2f2;
137
+ -moz-box-shadow: inset 0 1px 0 0 #f2f2f2;
138
+ box-shadow: inset 0 1px 0 0 #f2f2f2;
139
+ color: #163659;
140
+ cursor: pointer; }
141
+ button:active {
142
+ border: 1px solid #8c98a7;
143
+ -webkit-box-shadow: inset 0 0 4px 2px #abbccf, 0 0 1px 0 #eeeeee;
144
+ -moz-box-shadow: inset 0 0 4px 2px #abbccf, 0 0 1px 0 #eeeeee;
145
+ box-shadow: inset 0 0 4px 2px #abbccf, 0 0 1px 0 #eeeeee;
146
+ }
147
+
@@ -0,0 +1,56 @@
1
+ body { background-color: #fff; color: #333; }
2
+
3
+ body, p, ol, ul, td {
4
+ font-family: verdana, arial, helvetica, sans-serif;
5
+ font-size: 13px;
6
+ line-height: 18px;
7
+ }
8
+
9
+ pre {
10
+ background-color: #eee;
11
+ padding: 10px;
12
+ font-size: 11px;
13
+ }
14
+
15
+ a { color: #000; }
16
+ a:visited { color: #666; }
17
+ a:hover { color: #fff; background-color:#000; }
18
+
19
+ div.field, div.actions {
20
+ margin-bottom: 10px;
21
+ }
22
+
23
+ #notice {
24
+ color: green;
25
+ }
26
+
27
+ .field_with_errors {
28
+ padding: 2px;
29
+ background-color: red;
30
+ display: table;
31
+ }
32
+
33
+ #error_explanation {
34
+ width: 450px;
35
+ border: 2px solid red;
36
+ padding: 7px;
37
+ padding-bottom: 0;
38
+ margin-bottom: 20px;
39
+ background-color: #f0f0f0;
40
+ }
41
+
42
+ #error_explanation h2 {
43
+ text-align: left;
44
+ font-weight: bold;
45
+ padding: 5px 5px 5px 15px;
46
+ font-size: 12px;
47
+ margin: -7px;
48
+ margin-bottom: 0px;
49
+ background-color: #c00;
50
+ color: #fff;
51
+ }
52
+
53
+ #error_explanation ul li {
54
+ font-size: 12px;
55
+ list-style: square;
56
+ }
@@ -0,0 +1,12 @@
1
+ require 'glengarry/application_controller'
2
+
3
+ module Glengarry
4
+ class ApplicationController < ActionController::Base
5
+ cattr_accessor :authenticator
6
+
7
+ # This is a useful pattern I found in the Tolk source: https://github.com/tolk/tolk/blob/master/app/controllers/tolk/application_controller.rb
8
+ def authenticate
9
+ self.authenticator.bind(self).call if self.authenticator && self.authenticator.respond_to?(:call)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,78 @@
1
+ require_dependency "glengarry/application_controller"
2
+ require 'csv'
3
+
4
+ module Glengarry
5
+ class EmailLeadsController < ApplicationController
6
+
7
+ before_filter :authenticate, :except=>:create
8
+
9
+ def index
10
+ @email_leads = EmailLead.page(params[:page]).per(10)
11
+ @email_lead_count = EmailLead.count
12
+
13
+ respond_to do |format|
14
+ format.html # index.html.erb
15
+ format.json { render json: @email_leads }
16
+ end
17
+ end
18
+
19
+ def show
20
+ @email_lead = EmailLead.find(params[:id])
21
+
22
+ respond_to do |format|
23
+ format.html # show.html.erb
24
+ format.json { render json: @email_lead }
25
+ end
26
+ end
27
+
28
+ def create
29
+ @email_lead = EmailLead.new(params[:email_lead])
30
+ @email_lead.ip_address = request.ip
31
+ @email_lead.referer = request.referer
32
+
33
+ respond_to do |format|
34
+ if @email_lead.save
35
+ format.html { redirect_to :back, notice: ['Thank you.'] }
36
+ format.json { render json: @email_lead, status: :created, location: @email_lead }
37
+ else
38
+ format.html { redirect_to :back, notice: @email_lead.errors }
39
+ format.json { render json: @email_lead.errors, status: :invalid_email }
40
+ end
41
+ end
42
+ end
43
+
44
+ def destroy
45
+ @email_lead = EmailLead.find(params[:id])
46
+ @email_lead.destroy
47
+
48
+ respond_to do |format|
49
+ format.html { redirect_to email_leads_url }
50
+ format.json { head :no_content }
51
+ end
52
+ end
53
+
54
+ def download
55
+ respond_to do |format|
56
+ format.csv {
57
+ @emails = EmailLead.all
58
+ @columns = ["Email", "IP Address", "Referer", "Latitude", "Longitude", "City", "Country"].to_csv
59
+ @filename = "emails-#{Date.today.to_s(:db)}"
60
+
61
+ self.response.headers["Content-Type"] ||= 'text/csv'
62
+ self.response.headers["Content-Disposition"] = "attachment; filename=#{@filename}"
63
+ self.response.headers["Content-Transfer-Encoding"] = "binary"
64
+
65
+ self.response_body = Enumerator.new do |y|
66
+ @emails.each_with_index do |email, i|
67
+ if i == 0
68
+ y << @columns
69
+ end
70
+ y << [email.email, email.ip_address, email.referer, email.lat, email.long, email.city, email.country].to_csv
71
+ end
72
+ end
73
+ }
74
+ end
75
+ end
76
+ end
77
+ end
78
+
@@ -0,0 +1,10 @@
1
+ module Glengarry
2
+ module ApplicationHelper
3
+ def pagination_count
4
+ count = content_for(:email_count).to_i
5
+ phrase = count < 10 ? "Showing #{count} of #{count}" : "Showing 10 of #{count}"
6
+ return phrase if content_for?(:email_count)
7
+ "No Leads Yet"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,4 @@
1
+ module Glengarry
2
+ module DashboardHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Glengarry
2
+ module EmailLeadsHelper
3
+ end
4
+ end
@@ -0,0 +1,34 @@
1
+ require_relative '../../../lib/email_validator'
2
+
3
+ module Glengarry
4
+
5
+ class EmailLead < ActiveRecord::Base
6
+ extend Geocoder::Model::ActiveRecord
7
+
8
+ attr_accessible :email
9
+
10
+ validates :email, :presence => true, :uniqueness => true, :'Glengarry::Email'=>true
11
+
12
+ geocoded_by :ip_address, :latitude => :lat, :longitude => :long
13
+ reverse_geocoded_by :lat, :long do |obj, results|
14
+ obj.set_reversed_location(results)
15
+ end
16
+
17
+ after_validation :full_geocode
18
+
19
+ def set_reversed_location(results)
20
+ if geo = results.first
21
+ self.city = geo.city
22
+ self.country = geo.country
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def full_geocode
29
+ geocode
30
+ reverse_geocode
31
+ end
32
+ end
33
+
34
+ end
@@ -0,0 +1,45 @@
1
+ <%= form_for(@email_lead) do |f| %>
2
+ <% if @email_lead.errors.any? %>
3
+ <div id="error_explanation">
4
+ <h2><%= pluralize(@email_lead.errors.count, "error") %> prohibited this email_lead from being saved:</h2>
5
+
6
+ <ul>
7
+ <% @email_lead.errors.full_messages.each do |msg| %>
8
+ <li><%= msg %></li>
9
+ <% end %>
10
+ </ul>
11
+ </div>
12
+ <% end %>
13
+
14
+ <div class="field">
15
+ <%= f.label :email %><br />
16
+ <%= f.text_field :email %>
17
+ </div>
18
+ <div class="field">
19
+ <%= f.label :ip_address %><br />
20
+ <%= f.text_field :ip_address %>
21
+ </div>
22
+ <div class="field">
23
+ <%= f.label :referer %><br />
24
+ <%= f.text_field :referer %>
25
+ </div>
26
+ <div class="field">
27
+ <%= f.label :lat %><br />
28
+ <%= f.text_field :lat %>
29
+ </div>
30
+ <div class="field">
31
+ <%= f.label :long %><br />
32
+ <%= f.text_field :long %>
33
+ </div>
34
+ <div class="field">
35
+ <%= f.label :city %><br />
36
+ <%= f.text_field :city %>
37
+ </div>
38
+ <div class="field">
39
+ <%= f.label :country %><br />
40
+ <%= f.text_field :country %>
41
+ </div>
42
+ <div class="actions">
43
+ <%= f.submit %>
44
+ </div>
45
+ <% end %>
@@ -0,0 +1,6 @@
1
+ <h1>Editing email_lead</h1>
2
+
3
+ <%= render 'form' %>
4
+
5
+ <%= link_to 'Show', @email_lead %> |
6
+ <%= link_to 'Back', email_leads_path %>
@@ -0,0 +1,39 @@
1
+ <% content_for(:email_count) do %>
2
+ <%= @email_lead_count if @email_lead_count > 0%>
3
+ <% end %>
4
+
5
+ <% if @email_lead_count >0 %>
6
+ <a href="<%=download_csv_path%>.csv"><button>Download all as CSV</button></a>
7
+ <table>
8
+ <tr>
9
+ <th>Email</th>
10
+ <th>Ip address</th>
11
+ <th>Referer</th>
12
+ <th>Lat</th>
13
+ <th>Long</th>
14
+ <th>City</th>
15
+ <th>Country</th>
16
+ <th></th>
17
+ </tr>
18
+
19
+ <% @email_leads.each do |email_lead| %>
20
+ <tr>
21
+ <td><%= email_lead.email %></td>
22
+ <td><%= email_lead.ip_address %></td>
23
+ <td><%= email_lead.referer %></td>
24
+ <td><%= email_lead.lat %></td>
25
+ <td><%= email_lead.long %></td>
26
+ <td><%= email_lead.city %></td>
27
+ <td><%= email_lead.country %></td>
28
+ <td><%= link_to 'Destroy', email_lead, method: :delete, data: { confirm: 'Are you sure?' } %></td>
29
+ </tr>
30
+ <% end %>
31
+ <tr>
32
+ <td colspan="9">
33
+ <%= paginate @email_leads %>
34
+ </td>
35
+ </tr>
36
+ </table>
37
+ <% else %>
38
+ <h1>No Email Leads captured yet :(</h1>
39
+ <% end %>
@@ -0,0 +1,5 @@
1
+ <h1>New email_lead</h1>
2
+
3
+ <%= render 'form' %>
4
+
5
+ <%= link_to 'Back', email_leads_path %>
@@ -0,0 +1,40 @@
1
+ <p id="notice"><%= notice %></p>
2
+
3
+ <p>
4
+ <b>Email:</b>
5
+ <%= @email_lead.email %>
6
+ </p>
7
+
8
+ <p>
9
+ <b>Ip address:</b>
10
+ <%= @email_lead.ip_address %>
11
+ </p>
12
+
13
+ <p>
14
+ <b>Referer:</b>
15
+ <%= @email_lead.referer %>
16
+ </p>
17
+
18
+ <p>
19
+ <b>Lat:</b>
20
+ <%= @email_lead.lat %>
21
+ </p>
22
+
23
+ <p>
24
+ <b>Long:</b>
25
+ <%= @email_lead.long %>
26
+ </p>
27
+
28
+ <p>
29
+ <b>City:</b>
30
+ <%= @email_lead.city %>
31
+ </p>
32
+
33
+ <p>
34
+ <b>Country:</b>
35
+ <%= @email_lead.country %>
36
+ </p>
37
+
38
+
39
+ <%= link_to 'Edit', edit_email_lead_path(@email_lead) %> |
40
+ <%= link_to 'Back', email_leads_path %>
@@ -0,0 +1,21 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Glengarry</title>
5
+ <%= stylesheet_link_tag "glengarry/application", :media => "all" %>
6
+ <link href='http://fonts.googleapis.com/css?family=PT+Sans+Narrow:regular,bold' rel='stylesheet' type='text/css'>
7
+ <%= javascript_include_tag "glengarry/application" %>
8
+ <%= csrf_meta_tags %>
9
+ </head>
10
+ <body>
11
+ <header>
12
+ <h1>Captured Email Leads
13
+ <small><%= pagination_count %></small>
14
+ </h1>
15
+ </header>
16
+ <div id="page">
17
+ <%= yield %>
18
+ </div>
19
+
20
+ </body>
21
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,4 @@
1
+ Glengarry::Engine.routes.draw do
2
+ match 'email_leads/download' => 'EmailLeads#download', :as=>:download_csv
3
+ resources :email_leads
4
+ end
@@ -0,0 +1,15 @@
1
+ class CreateGlengarryEmailLeads < ActiveRecord::Migration
2
+ def change
3
+ create_table :glengarry_email_leads do |t|
4
+ t.string :email
5
+ t.string :ip_address
6
+ t.string :referer
7
+ t.float :lat
8
+ t.float :long
9
+ t.string :city
10
+ t.string :country
11
+
12
+ t.timestamps
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,36 @@
1
+ require 'mail'
2
+
3
+ module Glengarry
4
+ class EmailValidator < ActiveModel::EachValidator
5
+ def validate_each(record, attribute, value)
6
+ unless valid_email?(value)
7
+ msg = options[:message]
8
+ msg ||= I18n.t(:"validators.email.invalid", :default => "has invalid format")
9
+ record.errors[attribute] << msg
10
+ end
11
+ end
12
+
13
+ protected
14
+
15
+ # Internal: Takes an email and returns whether is invalid or not.
16
+ #
17
+ # email - A String email address to be validated.
18
+ #
19
+ # Returns true if email is valid.
20
+ def valid_email?(email)
21
+ mail = Mail::Address.new(email)
22
+
23
+ # We must check that value contains a domain and that value is
24
+ # an email address
25
+ result = mail.domain && mail.address == email
26
+ tree = mail.__send__(:tree)
27
+
28
+ # We need to dig into treetop. A valid domain must have
29
+ # dot_atom_text elements size > 1. Addresses like user@localhost
30
+ # are excluded. Treetop must respond to domain.
31
+ result && (tree.domain.dot_atom_text.elements.size > 1)
32
+ rescue => e
33
+ false
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ require 'kaminari'
3
+ require 'geocoder'
4
+ require 'jquery-rails'
5
+
6
+ require_relative '../email_validator'
7
+
8
+ module Glengarry
9
+ class Engine < ::Rails::Engine
10
+ isolate_namespace Glengarry
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module Glengarry
2
+ VERSION = "0.0.1"
3
+ end
data/lib/glengarry.rb ADDED
@@ -0,0 +1,4 @@
1
+ require "glengarry/engine"
2
+
3
+ module Glengarry
4
+ end
File without changes
metadata ADDED
@@ -0,0 +1,193 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: glengarry
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - John McDowall
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-04 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 3.2.7
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 3.2.7
30
+ - !ruby/object:Gem::Dependency
31
+ name: jquery-rails
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: kaminari
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: geocoder
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: sqlite3
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: rspec-rails
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: factory_girl_rails
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ description: I HATE THIS FIELD
127
+ email:
128
+ - john@mcdowall.info
129
+ executables: []
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - app/assets/images/glengarry/bg.png
134
+ - app/assets/javascripts/glengarry/application.js
135
+ - app/assets/javascripts/glengarry/dashboard.js
136
+ - app/assets/javascripts/glengarry/email_leads.js
137
+ - app/assets/stylesheets/glengarry/application.css
138
+ - app/assets/stylesheets/glengarry/dashboard.css
139
+ - app/assets/stylesheets/glengarry/email_leads.css.erb
140
+ - app/assets/stylesheets/scaffold.css
141
+ - app/controllers/glengarry/application_controller.rb
142
+ - app/controllers/glengarry/email_leads_controller.rb
143
+ - app/helpers/glengarry/application_helper.rb
144
+ - app/helpers/glengarry/dashboard_helper.rb
145
+ - app/helpers/glengarry/email_leads_helper.rb
146
+ - app/models/glengarry/email_lead.rb
147
+ - app/views/glengarry/email_leads/_form.html.erb
148
+ - app/views/glengarry/email_leads/edit.html.erb
149
+ - app/views/glengarry/email_leads/index.html.erb
150
+ - app/views/glengarry/email_leads/new.html.erb
151
+ - app/views/glengarry/email_leads/show.html.erb
152
+ - app/views/layouts/glengarry/application.html.erb
153
+ - config/routes.rb
154
+ - db/migrate/20120804175235_create_glengarry_email_leads.rb
155
+ - lib/email_validator.rb
156
+ - lib/glengarry/engine.rb
157
+ - lib/glengarry/version.rb
158
+ - lib/glengarry.rb
159
+ - lib/tasks/glengarry_tasks.rake
160
+ - MIT-LICENSE
161
+ - Rakefile
162
+ - README.md
163
+ homepage: https://github.com/johnmcdowall/glengarry
164
+ licenses: []
165
+ post_install_message:
166
+ rdoc_options: []
167
+ require_paths:
168
+ - lib
169
+ required_ruby_version: !ruby/object:Gem::Requirement
170
+ none: false
171
+ requirements:
172
+ - - ! '>='
173
+ - !ruby/object:Gem::Version
174
+ version: '0'
175
+ segments:
176
+ - 0
177
+ hash: -281059192529344362
178
+ required_rubygems_version: !ruby/object:Gem::Requirement
179
+ none: false
180
+ requirements:
181
+ - - ! '>='
182
+ - !ruby/object:Gem::Version
183
+ version: '0'
184
+ segments:
185
+ - 0
186
+ hash: -281059192529344362
187
+ requirements: []
188
+ rubyforge_project:
189
+ rubygems_version: 1.8.23
190
+ signing_key:
191
+ specification_version: 3
192
+ summary: A Rails 3.2 engine for capturing email leads.
193
+ test_files: []