Skip to content

Commit

Permalink
Merge pull request solidusio#44 from solidusio/braintree_configuration
Browse files Browse the repository at this point in the history
Add Braintree configuration to Spree::Store model
  • Loading branch information
adammathys authored Jan 9, 2017
2 parents 173db7b + 6f72a04 commit 5b5b7f0
Show file tree
Hide file tree
Showing 18 changed files with 244 additions and 7 deletions.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,23 @@ bundle
bundle exec rails g solidus_paypal_braintree:install
```

Store Configuration
-------------------

This gem adds a configuration model - `SolidusPaypalBraintree::Configuration` -
that belongs to `Spree::Store` as `braintree_configuration`. In multi-store
Solidus applications, this model allows admins to enable/disable payment types
on a per-store basis.

The migrations for this gem will add a default configuration to all stores that
has each payment type disabled. It also adds a `before_create` callback to
`Spree::Store` that builds a default configuration. You can customize the
default configuration that gets created by overriding the private
`build_default_configuration` method on `Spree::Store`.

A view override is provided that adds a `Braintree` tab to the admin settings
submenu. Admins can go here to edit the configuration for each store.

Testing
-------

Expand Down
15 changes: 15 additions & 0 deletions app/helpers/solidus_paypal_braintree/routes_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module SolidusPaypalBraintree
module RoutesHelper
def method_missing(method_sym, *arguments, &block)
if spree.respond_to?(method_sym)
spree.send(method_sym, arguments)
else
super
end
end

def respond_to_missing?(method_sym, include_private = false)
spree.respond_to?(method_sym) || super
end
end
end
5 changes: 5 additions & 0 deletions app/models/solidus_paypal_braintree/configuration.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class SolidusPaypalBraintree::Configuration < ApplicationRecord
belongs_to :store, class_name: 'Spree::Store'

validates :store, presence: true
end
11 changes: 11 additions & 0 deletions app/models/spree/store_decorator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Spree::Store.class_eval do
has_one :braintree_configuration, class_name: "SolidusPaypalBraintree::Configuration"

before_create :build_default_configuration

private

def build_default_configuration
build_braintree_configuration
end
end
6 changes: 6 additions & 0 deletions app/overrides/admin_navigation_menu.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Deface::Override.new(
virtual_path: "spree/admin/shared/_settings_sub_menu",
name: "solidus_paypal_braintree_admin_navigation_configuration",
insert_bottom: "[data-hook='admin_settings_sub_tabs']",
partial: "solidus_paypal_braintree/configurations/admin_tab"
)
9 changes: 9 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
en:
spree:
admin:
tab:
braintree: Braintree
solidus_paypal_braintree:
nonce: Nonce
token: Token
payment_type:
apple_pay_card: Apple Pay
pay_pal_account: PayPal
configurations:
title: Braintree Configurations
tab: Braintree
update_success: Successfully updated Braintree configurations.
update_error: An error occurred while updating Braintree configurations.
15 changes: 10 additions & 5 deletions config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
Rails.application.routes.draw do
namespace :solidus_paypal_braintree do
resource :checkout, only: [:update, :edit]
resource :client_token, only: [:create], format: :json
resource :transactions, only: [:create]
SolidusPaypalBraintree::Engine.routes.draw do
resource :checkout, only: [:update, :edit]
resource :client_token, only: [:create], format: :json
resource :transactions, only: [:create]

resources :configurations do
collection do
get :list
post :update
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class CreateSolidusPaypalBraintreeConfigurations < ActiveRecord::Migration
def change
create_table :solidus_paypal_braintree_configurations do |t|
t.boolean :paypal, null: false, default: false
t.boolean :apple_pay, null: false, default: false
t.integer :store_id, null: false, index: true, foreign_key: { references: :spree_stores }

t.timestamps null: false
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class AddBraintreeConfigurationToStores < ActiveRecord::Migration
def up
Spree::Store.all.each(&:create_braintree_configuration)
end

def down
SolidusPaypalBraintree::Configuration.joins(:store).destroy_all
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module SolidusPaypalBraintree
class ConfigurationsController < Spree::Admin::BaseController
helper RoutesHelper

def list
authorize! :list, SolidusPaypalBraintree::Configuration

@configurations = Spree::Store.all.map(&:braintree_configuration)
end

def update
authorize! :update, SolidusPaypalBraintree::Configuration

params = configurations_params[:configuration_fields]
if SolidusPaypalBraintree::Configuration.update(params.keys, params.values)
flash[:success] = t('update_success', scope: 'solidus_paypal_braintree.configurations')
else
flash[:error] = t('update_error', scope: 'solidus_paypal_braintree.configurations')
end
redirect_to action: :list
end

private

def configurations_params
params.require(:configurations).
permit(configuration_fields: [:paypal, :apple_pay])
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ def add_migrations
run 'bundle exec rake railties:install:migrations FROM=solidus_paypal_braintree'
end

def mount_engine
insert_into_file File.join('config', 'routes.rb'), after: "Rails.application.routes.draw do\n" do
"mount SolidusPaypalBraintree::Engine, at: '/solidus_paypal_braintree'"
end
end

def run_migrations
run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask('Would you like to run the migrations now? [Y/n]'))
if run_migrations
Expand Down
12 changes: 10 additions & 2 deletions lib/solidus_paypal_braintree/engine.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
module SolidusPaypalBraintree
class Engine < Rails::Engine
require 'spree/core'
isolate_namespace Spree
isolate_namespace SolidusPaypalBraintree
engine_name 'solidus_paypal_braintree'

# use rspec for tests
Expand All @@ -25,6 +24,10 @@ def self.frontend_available?
defined?(Spree::Frontend::Engine) == "constant"
end

def self.backend_available?
defined?(Spree::Backend::Engine) == "constant"
end

if frontend_available?
config.assets.precompile += [
'spree/frontend/solidus_paypal_braintree',
Expand All @@ -33,5 +36,10 @@ def self.frontend_available?
paths["app/controllers"] << "lib/controllers/frontend"
paths["app/views"] << "lib/views/frontend"
end

if backend_available?
paths["app/controllers"] << "lib/controllers/backend"
paths["app/views"] << "lib/views/backend"
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<%= tab :braintree, match_path: /braintree\/configurations/,
url: solidus_paypal_braintree.list_configurations_path
%>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<% content_for :page_title do %>
<%= t(:title, scope: 'solidus_paypal_braintree.configurations') %>
<% end %>

<%= form_for :configurations, url: solidus_paypal_braintree.configurations_path do |f| %>
<% @configurations.each do |config| %>
<div class="row">
<fieldset>
<h1><%= config.store.name %></h1>

<%= f.fields_for 'configuration_fields[]', config do |c| %>
<div class="field">
<%= c.label :paypal %>
<%= c.check_box :paypal %>
</div>
<div class="field">
<%= c.label :apple_pay %>
<%= c.check_box :apple_pay %>
</div>
<% end %>
</fieldset>
</div>
<% end %>

<%= submit_tag %>
<% end %>
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
require 'support/order_ready_for_payment'

RSpec.describe SolidusPaypalBraintree::CheckoutsController, type: :controller do
routes { SolidusPaypalBraintree::Engine.routes }

include_context 'order ready for payment'

describe 'PATCH update', vcr: { cassette_name: 'checkout/update' } do
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
require 'spec_helper'

describe SolidusPaypalBraintree::ClientTokensController do
routes { SolidusPaypalBraintree::Engine.routes }

cassette_options = { cassette_name: "braintree/token" }
describe "POST create", vcr: cassette_options do
let!(:gateway) { create_gateway }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
require 'spec_helper'

describe SolidusPaypalBraintree::ConfigurationsController, type: :controller do
routes { SolidusPaypalBraintree::Engine.routes }

let!(:store_1) { create :store }
let!(:store_2) { create :store }
let(:store_1_config) { store_1.braintree_configuration }
let(:store_2_config) { store_2.braintree_configuration }

stub_authorization!

describe "GET #list" do
subject { get :list }

it "assigns all store's configurations as @configurations" do
subject
expect(assigns(:configurations)).
to eq [store_1.braintree_configuration, store_2.braintree_configuration]
end

it "renders the correct view" do
expect(subject).to render_template :list
end
end

describe "POST #update" do
let(:configurations_params) do
{
configurations: {
configuration_fields: {
store_1_config.id.to_s => { paypal: true, apple_pay: true },
store_2_config.id.to_s => { paypal: true, apple_pay: false }
}
}
}
end

subject { post :update, configurations_params }

context "with valid parameters" do
it "updates the configuration" do
expect { subject }.to change { store_1_config.reload.paypal }.
from(false).to(true)
end

it "displays a success message to the user" do
subject
expect(flash[:success]).to eq "Successfully updated Braintree configurations."
end

it "displays all configurations" do
expect(subject).to redirect_to action: :list
end
end

context "with invalid parameters" do
before { allow(SolidusPaypalBraintree::Configuration).to receive(:update) { false } }

it "displays an error message to the user" do
subject
expect(flash[:error]).to eq "An error occurred while updating Braintree configurations."
end

it "returns the user to the edit page" do
expect(subject).to redirect_to action: :list
end
end
end
end
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
require 'spec_helper'

RSpec.describe SolidusPaypalBraintree::TransactionsController, type: :controller do
routes { SolidusPaypalBraintree::Engine.routes }

include_context "order ready for payment"

let(:payment_method) { create_gateway }
Expand Down

0 comments on commit 5b5b7f0

Please sign in to comment.