mirror of
https://github.com/Growstuff/growstuff.git
synced 2026-10-23 23:38:23 -04:00
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:
commit
b73c4db17a
21 files changed
+165
-23
No files matched your search
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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")
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in new issue
Block a user