Merge branch 'newsletter' of https://github.com/Skud/growstuff into Skud-newsletter

Conflicts:
	db/schema.rb
	spec/models/member_spec.rb
This commit is contained in:
Skud committed 2013-08-29 00:06:44 +10:00
commit b73c4db17a
21 files changed
+165 -23

No files matched your search

+2
View File
@@ -10,6 +10,8 @@ gem 'unicorn' # http server
gem 'cancan' # for checking member privileges
gem 'gibbon' # for Mailchimp newsletter subscriptions
# vendored activemerchant for testing- needed for bogus paypal
# gateway monkeypatch
gem 'activemerchant', '1.33.0',
+8
View File
@@ -106,6 +106,9 @@ GEM
friendly_id (4.0.9)
fssm (0.2.10)
geocoder (1.1.8)
gibbon (1.0.0)
httparty
multi_json (>= 1.3.4)
gravatar-ultimate (1.0.3)
haml (4.0.3)
tilt
@@ -116,6 +119,9 @@ GEM
railties (>= 3.1, < 4.1)
hashie (2.0.5)
hike (1.2.3)
httparty (0.11.0)
multi_json (~> 1.0)
multi_xml (>= 0.5.2)
i18n (0.6.1)
journey (1.0.4)
jquery-rails (3.0.4)
@@ -136,6 +142,7 @@ GEM
mime-types (1.23)
mini_portile (0.5.1)
multi_json (1.7.7)
multi_xml (0.5.5)
newrelic_rpm (3.6.5.130)
nokogiri (1.6.0)
mini_portile (~> 0.5.0)
@@ -251,6 +258,7 @@ DEPENDENCIES
flickraw
friendly_id
geocoder
gibbon
gravatar-ultimate
haml
haml-rails
+8
View File
@@ -5,4 +5,12 @@ class AdminController < ApplicationController
format.html # index.html.haml
end
end
def newsletter
authorize! :manage, :all
@members = Member.confirmed.wants_newsletter.all
respond_to do |format|
format.html # index.html.haml
end
end
end
+38 -2
View File
@@ -28,6 +28,7 @@ class Member < ActiveRecord::Base
scope :confirmed, where('confirmed_at IS NOT NULL')
scope :located, where("location <> ''")
scope :recently_signed_in, reorder('updated_at DESC')
scope :wants_newsletter, where(:newsletter => true)
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
@@ -38,7 +39,7 @@ class Member < ActiveRecord::Base
# Setup accessible (or protected) attributes for your model
attr_accessible :login_name, :email, :password, :password_confirmation,
:remember_me, :login, :tos_agreement, :show_email,
:remember_me, :login, :tos_agreement, :show_email, :newsletter,
:location, :latitude, :longitude, :send_notification_email, :bio
# set up geocoding
@@ -80,6 +81,8 @@ class Member < ActiveRecord::Base
# which can happen sometimes especially with FactoryGirl associations
after_create {|member| Account.find_or_create_by_member_id(:member_id => member.id) }
after_save :update_newsletter_subscription
# allow login via either login_name or email address
def self.find_first_by_auth_conditions(warden_conditions)
conditions = warden_conditions.dup
@@ -201,7 +204,8 @@ class Member < ActiveRecord::Base
return interesting_members
end
protected
private
def empty_unwanted_geocodes
if self.location.to_s == ''
self.latitude = nil
@@ -209,4 +213,36 @@ class Member < ActiveRecord::Base
end
end
def update_newsletter_subscription
if confirmed_at_changed? and newsletter # just signed up
newsletter_subscribe
elsif confirmed_at # i.e. after member's confirmed their account
if newsletter_changed? # edited member settings
if newsletter
newsletter_subscribe
else
newsletter_unsubscribe
end
end
end
end
def newsletter_subscribe
gb = Gibbon::API.new
res = gb.lists.subscribe({
:id => ENV['MAILCHIMP_NEWSLETTER_ID'],
:email => { :email => email },
:merge_vars => { :login_name => login_name },
:double_optin => false # they alredy confirmed their email with us
})
end
def newsletter_unsubscribe
gb = Gibbon::API.new
res = gb.lists.unsubscribe({
:id => ENV['MAILCHIMP_NEWSLETTER_ID'],
:email => { :email => email }
})
end
end
+1
View File
@@ -7,6 +7,7 @@
%li= link_to "Products", products_path
%li= link_to "Roles", roles_path
%li= link_to "Forums", forums_path
%li= link_to "Newsletter subscribers", admin_newsletter_path
%h2 Orders
+6
View File
@@ -0,0 +1,6 @@
-content_for :title, 'Newsletter subscribers'
%p
- @members.each do |m|
= m.email
%br/
@@ -0,0 +1,5 @@
The #{Growstuff::Application.config.site_name} newsletter is sent out
every few weeks. Check out our
= link_to 'past newsletters', 'http://blog.growstuff.org/category/newsletter/'
if you want to see the sort of thing we'll send you. Of course, we'll never spam you
or sell your email address, and you can unsubscribe any time.
@@ -21,6 +21,13 @@
= f.check_box :send_notification_email
Receive emailed copies of Inbox notifications.
.control-group
.controls
= f.check_box :newsletter
Subscribe to the #{Growstuff::Application.config.site_name} newsletter
.help-inline
= render :partial => 'newsletter_blurb'
%h2 Profile details
.control-group
%label.control-label
+8 -1
View File
@@ -29,7 +29,14 @@
.controls
= f.check_box :tos_agreement
I agree to the
= link_to('Terms of Service', url_for(:action => 'tos', :controller => '/policy'))
= succeed "." do
= link_to 'Terms of Service', url_for(:action => 'tos', :controller => '/policy')
.control-group
.controls
= f.check_box :newsletter, :checked => true
Subscribe to the #{Growstuff::Application.config.site_name} newsletter
.help-inline
= render :partial => 'newsletter_blurb'
.form-actions
= f.submit "Sign up", :class => 'btn btn-primary'
+5
View File
@@ -78,5 +78,10 @@ module Growstuff
:openssl_verify_mode => 'none'
}
Gibbon::API.api_key = ENV['MAILCHIMP_APIKEY']
Gibbon::API.timeout = 10
Gibbon::API.throws_exceptions = false
config.newsletter_list_id = ENV['MAILCHIMP_NEWSLETTER_ID']
end
end
+1
View File
@@ -117,6 +117,7 @@ Growstuff::Application.routes.draw do
match '/admin/orders' => 'admin/orders#index'
match '/admin/orders/:action' => 'admin/orders#:action'
match '/admin' => 'admin#index'
match '/admin/newsletter' => 'admin#newsletter', :as => :admin_newsletter
match '/admin/:action' => 'admin#:action'
end
+6
View File
@@ -31,3 +31,9 @@ export TWITTER_SECRET=""
# Get Flickr key from http://www.flickr.com/services/apps/create/apply/
export FLICKR_KEY=""
export FLICKR_SECRET=""
# Used for subscribing/unsubscribing people from the newsletter
export MAILCHIMP_APIKEY=""
# Used to identify the newsletter via the API
# Fetch list IDs using Gibbon: puts gb.lists.list.to_yaml
export MAILCHIMP_NEWSLETTER_ID=""
@@ -0,0 +1,5 @@
class AddNewsletterToMember < ActiveRecord::Migration
def change
add_column :members, :newsletter, :boolean
end
end
+7 -1
View File
@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20130826023159) do
ActiveRecord::Schema.define(:version => 20130828114516) do
create_table "account_types", :force => true do |t|
t.string "name", :null => false
@@ -87,6 +87,11 @@ ActiveRecord::Schema.define(:version => 20130826023159) do
add_index "gardens", ["owner_id"], :name => "index_gardens_on_user_id"
add_index "gardens", ["slug"], :name => "index_gardens_on_slug", :unique => true
create_table "gardens_members", :id => false, :force => true do |t|
t.integer "garden_id"
t.integer "member_id"
end
create_table "members", :force => true do |t|
t.string "email", :default => "", :null => false
t.string "encrypted_password", :default => "", :null => false
@@ -117,6 +122,7 @@ ActiveRecord::Schema.define(:version => 20130826023159) do
t.boolean "send_notification_email", :default => true
t.text "bio"
t.integer "plantings_count"
t.boolean "newsletter"
end
add_index "members", ["confirmation_token"], :name => "index_users_on_confirmation_token", :unique => true
+15
View File
@@ -2,4 +2,19 @@ require 'spec_helper'
describe AdminController do
login_member(:admin_member)
describe "GET admin/newsletter" do
it 'fetches the admin newsletter page' do
get :newsletter
response.should be_success
response.should render_template("admin/newsletter")
end
it 'assigns @members' do
m = FactoryGirl.create(:newsletter_recipient_member)
get :newsletter
assigns(:members).should eq [m]
end
end
end
+4
View File
@@ -15,6 +15,10 @@ FactoryGirl.define do
tos_agreement false
end
factory :newsletter_recipient_member do
newsletter true
end
factory :no_bio_member do
bio nil
end
+11 -19
View File
@@ -4,15 +4,10 @@ describe 'member' do
context 'valid member' do
before(:each) do
@member = FactoryGirl.build(:member)
end
it 'should save a basic member' do
@member.save.should be_true
@member = FactoryGirl.create(:member)
end
it 'should be fetchable from the database' do
@member.save
@member2 = Member.find(@member.id)
@member2.should be_an_instance_of Member
@member2.login_name.should match(/member\d+/)
@@ -20,40 +15,32 @@ describe 'member' do
end
it 'should have a friendly slug' do
@member.save
@member.slug.should match(/member\d+/)
end
it 'has a bio' do
@member.bio = 'I love seeds'
@member.save
@member.bio.should eq 'I love seeds'
end
it 'should have a default garden' do
@member.save
@member.gardens.size.should == 1
@member.gardens.count.should == 1
end
it 'should have a accounts entry' do
@member.save
@member.account.should be_an_instance_of Account
end
it "should have a default-type account by default" do
@member.save
@member.account.account_type.name.should eq Growstuff::Application.config.default_account_type
@member.is_paid?.should be_false
end
it "doesn't show email by default" do
@member.save
@member.show_email.should be_false
end
it 'should stringify as the login_name' do
@member.save
@member.to_s.should match(/member\d+/)
"#{@member}".should match(/member\d+/)
end
@@ -64,25 +51,21 @@ describe 'member' do
end
it 'should be able to fetch gardens' do
@member.save
@member.gardens.first.name.should eq "Garden"
end
it 'has many plantings' do
@member.save
@planting = FactoryGirl.create(:planting, :owner => @member)
@member.plantings.size.should eq 1
end
it "has many comments" do
@member.save
@comment1 = FactoryGirl.create(:comment, :author => @member)
@comment2 = FactoryGirl.create(:comment, :author => @member)
@member.comments.length.should == 2
end
it "has many forums" do
@member.save
@forum1 = FactoryGirl.create(:forum, :owner => @member)
@forum2 = FactoryGirl.create(:forum, :owner => @member)
@member.forums.length.should == 2
@@ -115,6 +98,15 @@ describe 'member' do
end
end
context 'newsletter scope' do
it 'finds newsletter recipients' do
@member1 = FactoryGirl.create(:member)
@member2 = FactoryGirl.create(:newsletter_recipient_member)
Member.wants_newsletter.should include @member2
Member.wants_newsletter.should_not include @member1
end
end
context 'same :login_name' do
it "should not allow two members with the same login_name" do
FactoryGirl.create(:member, :login_name => "bob")
+4
View File
@@ -14,4 +14,8 @@ describe 'admin/index.html.haml', :type => "view" do
assert_select "a", :href => roles_path
assert_select "a", :href => forums_path
end
it "has a link to newsletter subscribers" do
rendered.should contain "Newsletter subscribers"
end
end
+16
View File
@@ -0,0 +1,16 @@
require 'spec_helper'
describe 'admin/newsletter.html.haml', :type => "view" do
before(:each) do
@member = FactoryGirl.create(:admin_member)
sign_in @member
controller.stub(:current_user) { @member }
@subscriber = FactoryGirl.create(:newsletter_recipient_member)
assign(:members, [@subscriber])
render
end
it "lists newsletter subscribers by email" do
rendered.should contain @subscriber.email
end
end
@@ -30,6 +30,10 @@ describe 'devise/registrations/edit.html.haml', :type => "view" do
it 'has a checkbox for email notifications' do
assert_select "input[id=member_send_notification_email][type=checkbox]"
end
it 'has a checkbox for newsletter subscription' do
assert_select "input[id=member_newsletter][type=checkbox]"
end
end
context 'profile section' do
@@ -14,5 +14,9 @@ describe 'devise/registrations/new.html.haml', :type => "view" do
it 'should have some fields' do
rendered.should contain 'Email'
end
it 'has a checkbox for newsletter subscription' do
assert_select "input[id=member_newsletter][type=checkbox]"
end
end
end