glengarry 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: []