Compare commits
18 Commits
1-1-stable
...
2-0-stable
| Author | SHA1 | Date | |
|---|---|---|---|
| bcb041c553 | |||
| efb07409e9 | |||
| 868fddd7bc | |||
| f3c13a7175 | |||
|
|
7dabf1a520 | ||
|
|
52e7009c17 | ||
|
|
8d44a25199 | ||
|
|
e6f8d6b4cc | ||
|
|
1d9fab3942 | ||
|
|
f6d5812379 | ||
|
|
e2f33cd006 | ||
|
|
9360c63503 | ||
|
|
b381ede8e1 | ||
|
|
37fe465dd9 | ||
|
|
23317eb0fb | ||
|
|
4dc2d9d54f | ||
|
|
446a23ce3a | ||
|
|
fdd8536b5b |
8
.gitignore
vendored
8
.gitignore
vendored
@@ -4,11 +4,11 @@
|
||||
.DS_Store
|
||||
.idea
|
||||
.project
|
||||
.sass-cache
|
||||
coverage
|
||||
Gemfile.lock
|
||||
tmp
|
||||
nbproject
|
||||
pkg
|
||||
*.swp
|
||||
spec/dummy
|
||||
*.tmproj
|
||||
Gemfile.lock
|
||||
Guardfile
|
||||
|
||||
|
||||
1
.ruby-version
Normal file
1
.ruby-version
Normal file
@@ -0,0 +1 @@
|
||||
1.9.3@digital2
|
||||
19
Gemfile
19
Gemfile
@@ -1,12 +1,17 @@
|
||||
source 'http://rubygems.org'
|
||||
source 'https://rubygems.org'
|
||||
|
||||
# Provides basic authentication functionality for testing parts of your engine
|
||||
gem 'spree_auth_devise', :github => "spree/spree_auth_devise", :branch => '2-0-stable'
|
||||
|
||||
gemspec
|
||||
|
||||
group :test do
|
||||
if RUBY_PLATFORM.downcase.include? "darwin"
|
||||
gem 'guard-rspec'
|
||||
gem 'rb-fsevent'
|
||||
gem 'growl'
|
||||
end
|
||||
gem "shoulda-matchers"
|
||||
end
|
||||
|
||||
gem 'spree', '~> 1.1.3'
|
||||
# `rspec-rails` needs to be in the development group so that Rails generators work.
|
||||
group :development, :test do
|
||||
gem "rspec-rails", "~> 2.12"
|
||||
end
|
||||
|
||||
gem 'therubyracer'
|
||||
|
||||
41
LICENSE
41
LICENSE
@@ -1,21 +1,26 @@
|
||||
The MIT License
|
||||
Copyright (c) 2013 [name of plugin creator]
|
||||
All rights reserved.
|
||||
|
||||
Copyright (c) 2011 funkensturm.
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name Spree nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
40
README.md
Normal file
40
README.md
Normal file
@@ -0,0 +1,40 @@
|
||||
SpreeDigital
|
||||
============
|
||||
|
||||
Introduction goes here.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Add spree_digital to your Gemfile:
|
||||
|
||||
```ruby
|
||||
gem 'spree_digital'
|
||||
```
|
||||
|
||||
Bundle your dependencies and run the installation generator:
|
||||
|
||||
```shell
|
||||
bundle
|
||||
bundle exec rails g spree_digital:install
|
||||
```
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
Be sure to bundle your dependencies and then create a dummy test app for the specs to run against.
|
||||
|
||||
```shell
|
||||
bundle
|
||||
bundle exec rake test_app
|
||||
bundle exec rspec spec
|
||||
```
|
||||
|
||||
When testing your applications integration with this extension you may use it's factories.
|
||||
Simply add this require statement to your spec_helper:
|
||||
|
||||
```ruby
|
||||
require 'spree_digital/factories'
|
||||
```
|
||||
|
||||
Copyright (c) 2013 [name of extension creator], released under the New BSD License
|
||||
@@ -1,98 +0,0 @@
|
||||
h1. Spree Digital
|
||||
|
||||
This is a spree extension to enable downloadable products. The design goal is to keep it robust. It should survive future spree versions out of the box.
|
||||
|
||||
The master branch is compatible with Spree 1.1.x, <= 1.0 versions are referenced in the Versionfile.
|
||||
|
||||
The idea is simple. You attach a file to a Product (or a Variant of this Product) and when people buy it, they will receive a link via email where they can download it once. There are a few assumptions that spree_digital (currently) makes and it's important to be aware of them.
|
||||
|
||||
* The table structure of spree_core is not touched. Spree_digital lives parallel to spree_core and does not do any changes to your existing database, except adding two new tables.
|
||||
* The download links will be sent via email in the order confirmation (or "resend" from the admin section). The links do *not* appear in the order "overview" that the customer sees.
|
||||
* There should only be "live" payments. Once the order is checked-out, the download links will immediately be sent (i.e. in the order confirmation).
|
||||
* You should create a ShippingMethod based on the Digital Delivery calculator type. The default cost for digital delivery is 0, but you can define a flat rate (creating a per-item digital delivery fee would be possible as well).
|
||||
* One may buy several items of the same digital product in one cart. The customer will simply receive several links by doing so. This allows customer's to legally purchase multiple copies of the same product and maybe give one away to a friend.
|
||||
* The links will only work 3 times (but we tell the customer that it works only once). After 24 hours the links are deactivated. This should keep you reasonably free from complaints of people who are not capable of appropriately clicking on a link. They can try a whole day long, 3 times per link. The file should really be downloadable for weird customers. I understand that this is a little bit security by obscurity, but it's better than other solutions that I've seen. The number of clicks and days the links are valid for is customizable via preferences.
|
||||
* The file @views/order_mailer/confirm_email.text.erb@ is the only thing that should need customization. But since I assume you do that anyway, it doesn't hurt to do it when you're using spree_digital. The reason is that the download links are added to the confirmation email to the customer. "http://github.com/iloveitaly/spree-html-email":http://github.com/iloveitaly/spree-html-email also supports spree_digital.
|
||||
* A purchased product can be downloaded even if you disable the product immediately. You would have to remove the attached file in your admin section to prevent people from downloading purchased products.
|
||||
* File are uploaded to @rails_root/private@. Make sure it's symlinked in case you're using Capistrano.
|
||||
* You must add a views/spree/digitals/unauthorized.html.erb file to present an error message to the user if they exceed the download / days limit
|
||||
* We use send_file to send the files on download. Yes, it goes through the entire stack right now.
|
||||
|
||||
h2. Installation
|
||||
|
||||
I assume that you already have a Rails 3 Spree application up and running. If not, the "Spree Documentation":http://spreecommerce.com/documentation will help you getting started.
|
||||
|
||||
To make use of @digital_spree@, you need to add this line to your @Gemfile@:
|
||||
|
||||
<pre>
|
||||
gem 'spree_digital', :git => 'git://github.com/funkensturm/spree_digital.git', :branch => 'master'
|
||||
</pre>
|
||||
|
||||
The following terminal commands will copy the migration files to the corresponding directory in your Rails application and apply the migrations to your database.
|
||||
|
||||
<pre>
|
||||
rake spree_digital:install:migrations
|
||||
rake db:migrate
|
||||
</pre>
|
||||
|
||||
This should be all there is to do.
|
||||
|
||||
h3. Important!
|
||||
|
||||
You should create a ShippingMethod based on the Digital Delivery calculator type. It will be detected by spree_digital. Otherwise your customer will be forced to choose something like "UPS" even if they purchase only downloadable products.
|
||||
|
||||
h2. Usage
|
||||
|
||||
...
|
||||
|
||||
|
||||
h1. Developer Section
|
||||
|
||||
h3. Table Diagram
|
||||
|
||||
<img src="http://github.com/funkensturm/spree_digital/raw/master/doc/tables.png">
|
||||
|
||||
h3. Installation (for Developers)
|
||||
|
||||
Get the spree framework and spree_digital extension for it:
|
||||
|
||||
<pre>
|
||||
git clone git://github.com/spree/spree.git
|
||||
git clone git://github.com/funkensturm/spree_digital
|
||||
</pre>
|
||||
|
||||
Go into the spree directory and run the bundle command:
|
||||
|
||||
<pre>
|
||||
cd spree
|
||||
bundle install
|
||||
</pre>
|
||||
|
||||
Go into the spree_digital directory and do the same:
|
||||
|
||||
NOTE: At this point you may need to uncomment the stuff in the @Gemfile@ before you can start developing and testing!
|
||||
|
||||
<pre>
|
||||
cd spree_digital
|
||||
bundle install
|
||||
</pre>
|
||||
|
||||
Bring up the test application (you only need to do this whenever you fiddle around with the migrations) and then you can run the tests as you please.
|
||||
|
||||
<pre>
|
||||
rake test_app
|
||||
rake spec
|
||||
</pre>
|
||||
|
||||
This link may be very helpful to you: "http://github.com/spree/spree":http://github.com/spree/spree
|
||||
|
||||
h3. Authors
|
||||
|
||||
* "iloveitaly":http://github.com/iloveitaly/
|
||||
* "funkensturm":http://github.com/funkensturm
|
||||
|
||||
h3. License
|
||||
|
||||
Copyright (c) 2011 funkensturm.
|
||||
Released under the MIT License
|
||||
See "http://github.com/funkensturm/spree_digital/blob/master/LICENSE":LICENSE
|
||||
30
Rakefile
30
Rakefile
@@ -1,31 +1,17 @@
|
||||
require 'rake'
|
||||
require 'rake/testtask'
|
||||
require 'rake/packagetask'
|
||||
require 'rubygems/package_task'
|
||||
require 'bundler'
|
||||
Bundler::GemHelper.install_tasks
|
||||
|
||||
require 'rspec/core/rake_task'
|
||||
require 'spree/core/testing_support/common_rake'
|
||||
require 'spree/testing_support/extension_rake'
|
||||
|
||||
RSpec::Core::RakeTask.new
|
||||
|
||||
task :default => [:spec]
|
||||
|
||||
spec = eval(File.read('spree_digital.gemspec'))
|
||||
|
||||
Gem::PackageTask.new(spec) do |p|
|
||||
p.gem_spec = spec
|
||||
end
|
||||
|
||||
desc "Release to gemcutter"
|
||||
task :release => :package do
|
||||
require 'rake/gemcutter'
|
||||
Rake::Gemcutter::Tasks.new(spec).define
|
||||
Rake::Task['gem:push'].invoke
|
||||
end
|
||||
|
||||
desc "Regenerates a rails 3 app for testing"
|
||||
desc 'Generates a dummy app for testing'
|
||||
task :test_app do
|
||||
ENV['LIB_NAME'] = 'spree_digital'
|
||||
|
||||
ENV['LIB_NAME'] = 'spree_digital'
|
||||
|
||||
require File.join `bundle show spree_core`.chomp, 'lib/generators/spree/dummy/dummy_generator.rb'
|
||||
Spree::DummyGenerator.class_eval do
|
||||
def test_dummy_add_digital
|
||||
@@ -35,5 +21,5 @@ task :test_app do
|
||||
end
|
||||
end
|
||||
|
||||
Rake::Task['common:test_app'].invoke
|
||||
Rake::Task['extension:test_app'].invoke
|
||||
end
|
||||
|
||||
15
Versionfile
15
Versionfile
@@ -1,4 +1,11 @@
|
||||
"0.7.x" => { :ref => "eddaea63959586d123007cbca3be5bf9c5edb1a7" }
|
||||
"1.0.x" => { :ref => "a8c27750ef1cf9d0ad1a2a6ebe33307da900a5c1" }
|
||||
"1.1.x" => { :branch => "1-1-stable" }
|
||||
"1.2.x" => { :branch => "master" }
|
||||
# This file is used to designate compatibilty with different versions of Spree
|
||||
# Please see http://spreecommerce.com/documentation/extensions.html#versionfile for details
|
||||
|
||||
# Examples
|
||||
#
|
||||
# '1.2.x' => { :branch => 'master' }
|
||||
# '1.1.x' => { :branch => '1-1-stable' }
|
||||
# '1.0.x' => { :branch => '1-0-stable' }
|
||||
# '0.70.x' => { :branch => '0-70-stable' }
|
||||
# '0.40.x' => { :tag => 'v1.0.0', :version => '1.0.0' }
|
||||
|
||||
|
||||
1
app/assets/javascripts/admin/spree_digital.js
Normal file
1
app/assets/javascripts/admin/spree_digital.js
Normal file
@@ -0,0 +1 @@
|
||||
//= require admin/spree_backend
|
||||
1
app/assets/javascripts/store/spree_digital.js
Normal file
1
app/assets/javascripts/store/spree_digital.js
Normal file
@@ -0,0 +1 @@
|
||||
//= require store/spree_frontend
|
||||
3
app/assets/stylesheets/admin/spree_digital.css
Normal file
3
app/assets/stylesheets/admin/spree_digital.css
Normal file
@@ -0,0 +1,3 @@
|
||||
/*
|
||||
*= require admin/spree_backend
|
||||
*/
|
||||
3
app/assets/stylesheets/store/spree_digital.css
Normal file
3
app/assets/stylesheets/store/spree_digital.css
Normal file
@@ -0,0 +1,3 @@
|
||||
/*
|
||||
*= require store/spree_frontend
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
module Spree
|
||||
class Admin::DigitalsController < Spree::Admin::ResourceController
|
||||
belongs_to "spree/product", find_by: :permalink
|
||||
belongs_to "spree/product", :find_by => :permalink
|
||||
|
||||
protected
|
||||
def location_after_save
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
Spree::Admin::OrdersController.class_eval do
|
||||
def reset_digitals
|
||||
@order.reset_digital_links!
|
||||
flash[:notice] = t(:downloads_reset)
|
||||
redirect_to admin_order_url(@order)
|
||||
end
|
||||
end
|
||||
@@ -1,7 +1,7 @@
|
||||
module Spree
|
||||
class DigitalsController < Spree::BaseController
|
||||
class DigitalsController < Spree::StoreController
|
||||
ssl_required :show
|
||||
|
||||
|
||||
def show
|
||||
link = DigitalLink.find_by_secret(params[:secret])
|
||||
|
||||
@@ -19,9 +19,9 @@ module Spree
|
||||
Rails.logger.error "Missing Digital Item: #{attachment.path}"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
render :unauthorized
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,7 +4,7 @@ require_dependency 'spree/calculator'
|
||||
module Spree
|
||||
class Calculator::DigitalDelivery < Calculator::FlatRate
|
||||
def self.description
|
||||
I18n.t(:digital_delivery)
|
||||
Spree.t(:digital_delivery)
|
||||
end
|
||||
|
||||
def compute(object=nil)
|
||||
|
||||
@@ -2,12 +2,12 @@ module Spree
|
||||
class Digital < ActiveRecord::Base
|
||||
belongs_to :variant
|
||||
has_many :digital_links, :dependent => :destroy
|
||||
|
||||
|
||||
has_attached_file :attachment, :path => ":rails_root/private/digitals/:id/:basename.:extension"
|
||||
|
||||
|
||||
# TODO: Limit the attachment to one single file. Paperclip supports many by default :/
|
||||
|
||||
attr_accessible :variant_id, :attachment
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
@@ -9,7 +9,7 @@ Spree::LineItem.class_eval do
|
||||
|
||||
private
|
||||
|
||||
# Create the download link for this item if it is digital.
|
||||
# TODO there is no reason to create the digital links until the order is complete
|
||||
def create_digital_links
|
||||
digital_links.delete_all
|
||||
|
||||
|
||||
@@ -10,16 +10,11 @@ Spree::Order.class_eval do
|
||||
false
|
||||
end
|
||||
|
||||
# UPGRADE_CHECK this works as of spree 1.1.1; make sure to check the original function on upgrade
|
||||
|
||||
def available_shipping_methods(display_on = nil)
|
||||
return [] unless ship_address
|
||||
all_methods = Spree::ShippingMethod.all_available(self, display_on)
|
||||
|
||||
if self.digital?
|
||||
all_methods.detect { |m| m.calculator.class == Spree::Calculator::DigitalDelivery }.try { |d| [d] } || all_methods
|
||||
else
|
||||
all_methods
|
||||
def reset_digital_links!
|
||||
line_items.select(&:digital?).map(&:digital_links).flatten.each do |digital_link|
|
||||
digital_link.update_column :access_counter, 0
|
||||
digital_link.update_column :created_at, Time.now
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -2,11 +2,11 @@ Deface::Override.new(:virtual_path => "spree/shared/_order_details",
|
||||
:name => "add_digital_downloads_to_invoice",
|
||||
:insert_bottom => "td[data-hook='order_item_description']",
|
||||
:text => %q{
|
||||
<% if order.state == 'complete' and item.variant.digital? %>
|
||||
<% if order.payment_state == 'paid' and item.variant.digital? %>
|
||||
<%= content_tag(:p, :class => 'download_links') do %>
|
||||
<% item.digital_links.each do |digital_link| %>
|
||||
<% format = File.extname(digital_link.digital.attachment.path).downcase %>
|
||||
<%= link_to t(:digital_download, :type => t("digital_format#{format}")), digital_url(:host => Spree::Config.get(:site_url), :secret => digital_link.secret), :class => "btn #{format}" %>
|
||||
<%= link_to Spree.t(:digital_download, :type => Spree.t("digital_format#{format}")), digital_url(:host => Spree::Config.get(:site_url), :secret => digital_link.secret), :class => "btn #{format}" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
@@ -2,7 +2,7 @@ Deface::Override.new(:virtual_path => "spree/admin/shared/_product_tabs",
|
||||
:name => "add_digital_versions_to_admin_product_tabs",
|
||||
:insert_bottom => "[data-hook='admin_product_tabs'], #admin_product_tabs[data-hook]",
|
||||
:text => " <li<%== ' class=\"active\"' if current == \"Digital Versions\" %>>
|
||||
<%= link_to t(\"digital_versions\"), admin_product_digitals_path(@product) %>
|
||||
<%= link_to_with_icon 'icon-tasks', Spree.t(:digital_versions), admin_product_digitals_path(@product) %>
|
||||
</li>
|
||||
",
|
||||
:disabled => false)
|
||||
|
||||
7
app/overrides/add_reset_digitals_to_admin_orders.rb
Normal file
7
app/overrides/add_reset_digitals_to_admin_orders.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
Deface::Override.new(:virtual_path => "spree/admin/shared/_order_tabs",
|
||||
:name => "add_reset_digitals_to_admin_orders",
|
||||
:insert_after => ".sidebar",
|
||||
:text => %q{
|
||||
<%= content_tag(:p, button_link_to(Spree.t(:reset_downloads), reset_digitals_admin_order_url(@order)), class: 'clear') if @order.digital? or true %>
|
||||
},
|
||||
:disabled => false)
|
||||
@@ -1,5 +1,5 @@
|
||||
<% if digital.attachment_file_name.present? %>
|
||||
<%= digital.attachment_file_name %> (<%= number_to_human_size(digital.attachment_file_size) %>)
|
||||
<% else %>
|
||||
<%=t 'broken_file' %>
|
||||
<%=Spree.t 'broken_file' %>
|
||||
<% end %>
|
||||
|
||||
@@ -1,34 +1,33 @@
|
||||
<div>
|
||||
<div>
|
||||
<%= form_for(:digital, :url => admin_product_digitals_path(@product), :method => :create, :multipart => true ) do |f| %>
|
||||
<fieldset>
|
||||
<legend><%= Spree::Variant.model_name.human %> "<%= variant.options_text %>"</legend>
|
||||
|
||||
<%= f.field_container :current_file do %>
|
||||
<strong><%=t 'files' %>:</strong>
|
||||
<strong><%=Spree.t 'files' %>:</strong>
|
||||
<% if variant.digital? %>
|
||||
<ul>
|
||||
<% variant.digitals.each do |digital| %>
|
||||
<li>
|
||||
<%= render digital %>
|
||||
<%= link_to t("delete_file"), admin_product_digital_url(@product, digital), :confirm => t('delete_file_cofirmation', :filename => digital.attachment_file_name), :method => :delete %>
|
||||
<%= link_to Spree.t(:delete_file), admin_product_digital_url(@product, digital), :confirm => Spree.t(:delete_file_cofirmation, :filename => digital.attachment_file_name), :method => :delete %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<% else %>
|
||||
<%=t 'none' %>
|
||||
<%=Spree.t 'none' %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<p class="form-buttons">
|
||||
<%= f.field_container :file do %>
|
||||
<%= f.label :file, t("new_file") %> <span class="required">*</span><br/>
|
||||
<%= f.label :file, Spree.t("new_file") %> <span class="required">*</span><br/>
|
||||
<%= f.file_field :attachment %>
|
||||
<% end %>
|
||||
|
||||
<%= hidden_field_tag 'digital[variant_id]', variant.id %>
|
||||
|
||||
<%= button t('spree_digital.upload') %>
|
||||
<%= button Spree.t('spree_digital.upload') %>
|
||||
</p>
|
||||
|
||||
</fieldset>
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
<% end %>
|
||||
|
||||
<% else %>
|
||||
This product has no variants.
|
||||
<%= Spree.t :product_without_variants %>
|
||||
|
||||
<% if @product.master.digital? %>
|
||||
A digital version of this product currently exists:
|
||||
<%= Spree.t :digital_exists %>
|
||||
<%= render @product.master.digitals %>
|
||||
<% end %>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<% if digital.attachment_file_name.present? %>
|
||||
<%= digital.attachment_file_name %> (<%= number_to_human_size(digital.attachment_file_size) %>)
|
||||
<% else %>
|
||||
<%=t 'broken_file' %>
|
||||
<%=Spree.t 'broken_file' %>
|
||||
<% end %>
|
||||
|
||||
9
app/views/spree/digitals/unauthorized.html.erb
Normal file
9
app/views/spree/digitals/unauthorized.html.erb
Normal file
@@ -0,0 +1,9 @@
|
||||
<% if defined?(SpreeFancy) %>
|
||||
<% content_for :subheader do %>
|
||||
<h1><%= t('.unauthorized') %></h1>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<h1><%= t('.unauthorized') %></h1>
|
||||
<% end %>
|
||||
|
||||
<%= t('.explained') %>
|
||||
@@ -1,17 +1,28 @@
|
||||
en:
|
||||
digital_versions: Digital Versions
|
||||
current_file: Current File
|
||||
new_file: New File
|
||||
delete_file: Delete this file
|
||||
broken_file: Warning! this file is broken
|
||||
delete_file_cofirmation: Are you sure you want to delete the file %{filename}?
|
||||
digital_delivery: Digital Delivery
|
||||
digital_download: Download %{type} ↓
|
||||
digital_download_links: Digital Download Links
|
||||
digital_format:
|
||||
mp3: Audio MP3
|
||||
mobi: Kindle eBook
|
||||
epub: ePub eBook
|
||||
pdf: pdf eBook
|
||||
spree_digital:
|
||||
upload: Upload
|
||||
spree:
|
||||
broken_file: Warning! this file is broken
|
||||
current_file: Current File
|
||||
delete_file: Delete this file
|
||||
delete_file_cofirmation: Are you sure you want to delete the file %{filename}?
|
||||
digital_delivery: Digital Delivery
|
||||
digital_download: Download %{type} ↓
|
||||
digital_download_links: Digital Download Links
|
||||
digital_format:
|
||||
mp3: Audio MP3
|
||||
mobi: Kindle eBook
|
||||
epub: ePub eBook
|
||||
pdf: pdf eBook
|
||||
gz: Archive
|
||||
digital_versions: Digital Versions
|
||||
downloads_reset: Digital Downloads Reset
|
||||
new_file: New File
|
||||
reset_downloads: Reset Digital Downloads
|
||||
spree:
|
||||
digitals:
|
||||
unauthorized:
|
||||
explained: This download link has expired.
|
||||
unauthorized: Unauthorized
|
||||
spree_digital:
|
||||
upload: Upload
|
||||
product_without_variants: This product has no variants.
|
||||
digital_exists: 'A digital version of this product currently exists:'
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
it:
|
||||
digital_versions: Versioni Digitali
|
||||
current_file: File Corrente
|
||||
new_file: Nuovo File
|
||||
delete_file: Elimina questo file
|
||||
broken_file: Attenzione! questo file sembra essere rotto
|
||||
delete_file_cofirmation: Sei sicuro di voler eliminare il file %{filename}?
|
||||
digital_delivery: Consegna Digitale
|
||||
digital_download: Download %{type} ↓
|
||||
digital_download_links: Link al Download Digitale
|
||||
digital_format:
|
||||
mp3: Audio MP3
|
||||
mobi: Kindle eBook
|
||||
epub: ePub eBook
|
||||
pdf: pdf eBook
|
||||
spree_digital:
|
||||
upload: Upload
|
||||
|
||||
spree:
|
||||
broken_file: Attenzione! questo file sembra essere rotto
|
||||
current_file: File Corrente
|
||||
delete_file: Elimina questo file
|
||||
delete_file_cofirmation: Sei sicuro di voler eliminare il file %{filename}?
|
||||
digital_delivery: Consegna Digitale
|
||||
digital_download: Download %{type} ↓
|
||||
digital_download_links: Link al Download Digitale
|
||||
digital_format:
|
||||
mp3: Audio MP3
|
||||
mobi: Kindle eBook
|
||||
epub: ePub eBook
|
||||
pdf: pdf eBook
|
||||
digital_versions: Versioni Digitali
|
||||
new_file: Nuovo File
|
||||
spree:
|
||||
digitals:
|
||||
unauthorized:
|
||||
explained: This download link has expired.
|
||||
unauthorized: Unauthorized
|
||||
spree_digital:
|
||||
upload: Upload
|
||||
@@ -1,12 +1,15 @@
|
||||
ja:
|
||||
digital_versions: デジタル版
|
||||
|
||||
current_file: 現在のバージョン
|
||||
new_file: 新しいファイル
|
||||
upload: アップロード
|
||||
delete_file: このファイルを削除
|
||||
broken_file: 注意! このファイルが壊れている!
|
||||
delete_file_cofirmation: 本当に「%{filename}」を削除しても宜しいですか?
|
||||
|
||||
digital_shipping: ダウンロードリンクを<strong>%{email}</strong>に送ります
|
||||
|
||||
spree:
|
||||
broken_file: 注意! このファイルが壊れている!
|
||||
current_file: 現在のバージョン
|
||||
delete_file: このファイルを削除
|
||||
delete_file_cofirmation: 本当に「%{filename}」を削除しても宜しいですか?
|
||||
digital_shipping: ダウンロードリンクを<strong>%{email}</strong>に送ります
|
||||
digital_versions: デジタル版
|
||||
new_file: 新しいファイル
|
||||
spree:
|
||||
digitals:
|
||||
unauthorized:
|
||||
explained: This download link has expired.
|
||||
unauthorized: Unauthorized
|
||||
upload: アップロード
|
||||
|
||||
@@ -3,8 +3,13 @@ Spree::Core::Engine.routes.draw do
|
||||
resources :products do
|
||||
resources :digitals
|
||||
end
|
||||
end
|
||||
|
||||
get '/digital/:secret', :to => 'digitals#show', :via => :get, :as => 'digital', :constraints => { :secret => /[a-zA-Z0-9]{30}/ }
|
||||
|
||||
end
|
||||
resources :orders do
|
||||
member do
|
||||
get :reset_digitals
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
get '/digital/:secret', :to => 'digitals#show', :via => :get, :as => 'digital', :constraints => { :secret => /[a-zA-Z0-9]{30}/ }
|
||||
end
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
module SpreeDigital
|
||||
module Generators
|
||||
class InstallGenerator < Rails::Generators::Base
|
||||
|
||||
# def add_javascripts
|
||||
# append_file "app/assets/javascripts/store/all.js", "//= require store/spree_digital\n"
|
||||
# append_file "app/assets/javascripts/admin/all.js", "//= require admin/spree_digital\n"
|
||||
# end
|
||||
|
||||
# def add_stylesheets
|
||||
# inject_into_file "app/assets/stylesheets/store/all.css", " *= require store/spree_digital\n",
|
||||
# :before => /\*\//, :verbose => true
|
||||
# inject_into_file "app/assets/stylesheets/admin/all.css", " *= require admin/spree_digital\n",
|
||||
# :before => /\*\//, :verbose => true
|
||||
# end
|
||||
|
||||
|
||||
class_option :auto_run_migrations, :type => :boolean, :default => false
|
||||
|
||||
def add_javascripts
|
||||
append_file 'app/assets/javascripts/store/all.js', "//= require store/spree_digital\n"
|
||||
append_file 'app/assets/javascripts/admin/all.js', "//= require admin/spree_digital\n"
|
||||
end
|
||||
|
||||
def add_stylesheets
|
||||
inject_into_file 'app/assets/stylesheets/store/all.css', " *= require store/spree_digital\n", :before => /\*\//, :verbose => true
|
||||
inject_into_file 'app/assets/stylesheets/admin/all.css', " *= require admin/spree_digital\n", :before => /\*\//, :verbose => true
|
||||
end
|
||||
|
||||
def add_migrations
|
||||
run 'bundle exec rake railties:install:migrations FROM=spree_digital'
|
||||
end
|
||||
|
||||
|
||||
def run_migrations
|
||||
res = ask "Would you like to run the migrations now? [Y/n]"
|
||||
if res == "" || res.downcase == "y"
|
||||
run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask 'Would you like to run the migrations now? [Y/n]')
|
||||
if run_migrations
|
||||
run 'bundle exec rake db:migrate'
|
||||
else
|
||||
puts "Skipping rake db:migrate, don't forget to run it!"
|
||||
puts 'Skipping rake db:migrate, don\'t forget to run it!'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
module SpreeDigital
|
||||
class Engine < Rails::Engine
|
||||
require 'spree/core'
|
||||
isolate_namespace Spree
|
||||
engine_name 'spree_digital'
|
||||
|
||||
config.autoload_paths += %W(#{config.root}/lib)
|
||||
|
||||
# use rspec for tests
|
||||
config.generators do |g|
|
||||
g.test_framework :rspec
|
||||
end
|
||||
|
||||
initializer "spree.spree_digital.preferences", :after => "spree.environment" do |app|
|
||||
Spree::DigitalConfiguration = Spree::SpreeDigitalConfiguration.new
|
||||
end
|
||||
@@ -11,10 +18,10 @@ module SpreeDigital
|
||||
initializer "spree.register.digital_shipping", :after => 'spree.register.calculators' do |app|
|
||||
app.config.spree.calculators.shipping_methods << Spree::Calculator::DigitalDelivery
|
||||
end
|
||||
|
||||
|
||||
def self.activate
|
||||
Dir.glob(File.join(File.dirname(__FILE__), "../../app/**/*_decorator*.rb")) do |c|
|
||||
Rails.application.config.cache_classes ? require(c) : load(c)
|
||||
Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/*_decorator*.rb')) do |c|
|
||||
Rails.configuration.cache_classes ? require(c) : load(c)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
28
lib/spree_digital/factories.rb
Normal file
28
lib/spree_digital/factories.rb
Normal file
@@ -0,0 +1,28 @@
|
||||
FactoryGirl.define do
|
||||
# Define your Spree extensions Factories within this file to enable applications, and other extensions to use and override them.
|
||||
#
|
||||
# Example adding this to your spec_helper will load these Factories for use:
|
||||
# require 'spree_digital/factories'
|
||||
|
||||
factory :digital, :class => Spree::Digital do |f|
|
||||
# TODO good to assign variant association if no association is manually defined
|
||||
# f.variant { |p| p.association(:variant) }
|
||||
|
||||
attachment_content_type 'application/octet-stream'
|
||||
attachment_file_name 'a_great_book.epub'
|
||||
end
|
||||
|
||||
factory :digital_link, :class => Spree::DigitalLink do |f|
|
||||
f.digital { |p| p.association(:digital) }
|
||||
f.line_item { |p| p.association(:line_item) }
|
||||
end
|
||||
|
||||
factory :digital_shipping_calculator, class: Spree::Calculator::DigitalDelivery do |c|
|
||||
after(:create) { |c| c.set_preference(:amount, 0) }
|
||||
end
|
||||
|
||||
factory :digital_shipping_method, parent: :shipping_method do |f|
|
||||
name "Digital Delivery"
|
||||
calculator { FactoryGirl.build :digital_shipping_calculator }
|
||||
end
|
||||
end
|
||||
147
readme.md
Normal file
147
readme.md
Normal file
@@ -0,0 +1,147 @@
|
||||
# Spree Digital
|
||||
|
||||
This is a spree extension to enable downloadable products (ebooks, MP3s, videos, etc).
|
||||
|
||||
The master branch is compatible with Spree 1.2.x. 1.0.x - 1.1.x versions are available, check the `Versionfile`.
|
||||
|
||||
This documentation is not complete and possibly out of date in some cases. There are features that have been implemented that are not documented here, please look at the source for complete documentation.
|
||||
|
||||
The idea is simple. You attach a file to a Product (or a Variant of this Product) and when people buy it, they will receive a link via email where they can download it once. There are a few assumptions that spree_digital (currently) makes and it's important to be aware of them.
|
||||
|
||||
* The table structure of spree_core is not touched. Spree digital lives parallel to spree_core and does change the existing database, except adding two new tables.
|
||||
* The download links will be sent via email in the order confirmation (or "resend" from the admin section). The links do *not* appear in the order "overview" that the customer sees. Adding download buttons to `OrdersController#show` is easy, [check out this gist](https://gist.github.com/3187793#file_add_spree_digital_buttons_to_invoice.rb).
|
||||
* Once the order is checked-out, the download links will immediately be sent (i.e. in the order confirmation). You'll have to modify the system to support 'delayed' payments (like a billable account).
|
||||
* You should create a ShippingMethod based on the Digital Delivery calculator type. The default cost for digital delivery is 0, but you can define a flat rate (creating a per-item digital delivery fee would be possible as well). Checkout the [source code](https://github.com/halo/spree_digital/blob/master/app/models/spree/calculator/digital_delivery.rb) for the Digital Delivery calculator for more information.
|
||||
* One may buy several items of the same digital product in one cart. The customer will simply receive several links by doing so. This allows customer's to legally purchase multiple copies of the same product and maybe give one away to a friend.
|
||||
* You can set how many times (clicks) the users downloads will work. You can also set how long the users links will work (expiration). For more information, [check out the preferences object](https://github.com/halo/spree_digital/blob/master/lib/spree/spree_digital_configuration.rb)
|
||||
* The file `views/order_mailer/confirm_email.text.erb` is the only thing that should need customization. If you are looking for HTML emails, [this branch of spree-html-email](http://github.com/iloveitaly/spree-html-email) supports spree_digital
|
||||
* A purchased product can be downloaded even if you disable the product immediately. You would have to remove the attached file in your admin section to prevent people from downloading purchased products.
|
||||
* File are uploaded to `rails_root/private`. Make sure it's symlinked in case you're using Capistrano. If you want to change the upload path, [check out this gist](https://gist.github.com/3187793#file_spree_digital_path_change_decorator.rb)
|
||||
* You must add a `views/spree/digitals/unauthorized.html.erb` file to customize an error message to the user if they exceed the download / days limit
|
||||
* We use send_file to send the files on download. See below for instructions on how to push file downloading off to nginx.
|
||||
|
||||
## Installation
|
||||
|
||||
Add this line to your gemfile:
|
||||
|
||||
```shell
|
||||
gem 'spree_digital', :git => 'git://github.com/dlage/spree_digital.git', :branch => 'master'
|
||||
```
|
||||
|
||||
The following terminal commands will copy the migration files to the corresponding directory in your Rails application and apply the migrations to your database.
|
||||
|
||||
```shell
|
||||
bundle exec rails g spree_digital:install
|
||||
bundle exec rake db:migrate
|
||||
```
|
||||
|
||||
Then set any preferences.
|
||||
|
||||
### Shipping Configuration
|
||||
|
||||
You should create a ShippingMethod based on the Digital Delivery calculator type. It will be detected by `spree_digital`. Otherwise your customer will be forced to choose something like "UPS" even if they purchase only downloadable products.
|
||||
|
||||
### Improving File Downloading: `send_file` + nginx
|
||||
|
||||
Without customization, all file downloading will route through the rails stack. This means that if you have two workers, and two customers are downloading files, your server is maxed out and will be unresponsive until the downloads have finished.
|
||||
|
||||
Luckily there is an easy way around this: pass off file downloading to nginx (or apache, etc). Take a look at [this article](http://blog.kiskolabs.com/post/637725747/nginx-rails-send-file) for a good explanation.
|
||||
|
||||
```
|
||||
# in your app's source
|
||||
# config/environments/production.rb
|
||||
|
||||
# Specifies the header that your server uses for sending files
|
||||
# config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
|
||||
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
|
||||
|
||||
|
||||
# on your server
|
||||
# /etc/nginx/sites-available/spree-secure
|
||||
upstream unicorn_spree_secure {
|
||||
server unix:/data/spree/shared/sockets/unicorn.sock fail_timeout=0;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443;
|
||||
...
|
||||
|
||||
location / {
|
||||
proxy_set_header X_FORWARDED_PROTO https;
|
||||
...
|
||||
|
||||
proxy_set_header X-Sendfile-Type X-Accel-Redirect;
|
||||
proxy_set_header X-Accel-Mapping /data/spree/shared/uploaded-files/digitals/=/digitals/;
|
||||
|
||||
...
|
||||
}
|
||||
|
||||
location /digitals/ {
|
||||
internal;
|
||||
root /data/spree/shared/uploaded-files/;
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
References:
|
||||
|
||||
* [Gist of example config](https://gist.github.com/416004)
|
||||
* [Change paperclip's upload / download path](https://gist.github.com/3187793#file_spree_digital_path_change_decorator.rb)
|
||||
* ["X-Accel-Mapping header missing" in nginx error log](http://stackoverflow.com/questions/6237016/message-x-accel-mapping-header-missing-in-nginx-error-log)
|
||||
* [Another good, but older, explanation](http://kovyrin.net/2006/11/01/nginx-x-accel-redirect-php-rails/)
|
||||
|
||||
## Usage
|
||||
|
||||
### Table Diagram
|
||||
|
||||
<img src="http://github.com/halo/spree_digital/raw/master/doc/tables.png">
|
||||
|
||||
### Installation
|
||||
|
||||
Get the spree framework and spree_digital extension for it:
|
||||
|
||||
```shell
|
||||
git clone git://github.com/spree/spree.git
|
||||
git clone git://github.com/dlage/spree_digital.git
|
||||
```
|
||||
|
||||
Go into the spree directory and run the bundle command:
|
||||
|
||||
```shell
|
||||
cd spree
|
||||
bundle install
|
||||
```
|
||||
|
||||
Go into the spree_digital directory and do the same:
|
||||
|
||||
NOTE: At this point you may need to uncomment the stuff in the `Gemfile` before you can start developing and testing!
|
||||
|
||||
```shell
|
||||
cd spree_digital
|
||||
bundle install
|
||||
```
|
||||
|
||||
Bring up the test application (you only need to do this whenever you fiddle around with the migrations) and then you can run the tests as you please.
|
||||
|
||||
```shell
|
||||
rake test_app
|
||||
rake spec
|
||||
```
|
||||
|
||||
This link may be very helpful to you: [http://github.com/spree/spree](http://github.com/spree/spree)
|
||||
|
||||
### Authors
|
||||
|
||||
* [iloveitaly](http://github.com/iloveitaly/)
|
||||
* [halo](http://github.com/halo)
|
||||
* [dlage](http://github.com/dlage)
|
||||
|
||||
### License
|
||||
|
||||
Copyright (c) 2011 funkensturm.
|
||||
Released under the MIT License
|
||||
See [LICENSE](http://github.com/funkensturm/spree_digital/blob/master/LICENSE)
|
||||
7
script/rails
Normal file
7
script/rails
Normal file
@@ -0,0 +1,7 @@
|
||||
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
|
||||
|
||||
ENGINE_ROOT = File.expand_path('../..', __FILE__)
|
||||
ENGINE_PATH = File.expand_path('../../lib/spree_digital/engine', __FILE__)
|
||||
|
||||
require 'rails/all'
|
||||
require 'rails/engine/commands'
|
||||
@@ -1,6 +0,0 @@
|
||||
FactoryGirl.define do
|
||||
factory :digital, :class => Spree::Digital do |f|
|
||||
# TODO good to assign variant association if no association is manually defined
|
||||
# f.variant { |p| p.association(:variant) }
|
||||
end
|
||||
end
|
||||
@@ -1,6 +0,0 @@
|
||||
FactoryGirl.define do
|
||||
factory :digital_link, :class => Spree::DigitalLink do |f|
|
||||
f.digital { |p| p.association(:digital) }
|
||||
f.line_item { |p| p.association(:line_item) }
|
||||
end
|
||||
end
|
||||
@@ -1,12 +0,0 @@
|
||||
FactoryGirl.define do
|
||||
# https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#modifying-factories
|
||||
|
||||
factory :digital_shipping_calculator, class: Spree::Calculator::DigitalDelivery do |c|
|
||||
after_create { |c| c.set_preference(:amount, 0) }
|
||||
end
|
||||
|
||||
factory :digital_shipping_method, parent: :shipping_method do |f|
|
||||
name "Digital Delivery"
|
||||
calculator { FactoryGirl.build :digital_shipping_calculator }
|
||||
end
|
||||
end
|
||||
@@ -4,9 +4,9 @@ describe Spree::Order do
|
||||
context "#add_variant" do
|
||||
it "should add digital Variants of quantity 1 to an order" do
|
||||
order = FactoryGirl.create(:order)
|
||||
order.add_variant variant1 = FactoryGirl.create(:variant, :digitals => [FactoryGirl.create(:digital)])
|
||||
order.add_variant variant2 = FactoryGirl.create(:variant, :digitals => [FactoryGirl.create(:digital)])
|
||||
order.add_variant variant3 = FactoryGirl.create(:variant, :digitals => [FactoryGirl.create(:digital)])
|
||||
order.contents.add variant1 = FactoryGirl.create(:variant, :digitals => [FactoryGirl.create(:digital)]), 1
|
||||
order.contents.add variant2 = FactoryGirl.create(:variant, :digitals => [FactoryGirl.create(:digital)]), 1
|
||||
order.contents.add variant3 = FactoryGirl.create(:variant, :digitals => [FactoryGirl.create(:digital)]), 1
|
||||
order.line_items.first.variant.should == variant1
|
||||
order.line_items.second.variant.should == variant2
|
||||
order.line_items.third.variant.should == variant3
|
||||
@@ -15,9 +15,9 @@ describe Spree::Order do
|
||||
it "should handle quantity higher than 1 when adding one specific digital Variant" do
|
||||
order = FactoryGirl.create(:order)
|
||||
digital_variant = FactoryGirl.create(:variant, :digitals => [FactoryGirl.create(:digital)])
|
||||
order.add_variant digital_variant, 3
|
||||
order.contents.add digital_variant, 3
|
||||
order.line_items.first.quantity.should == 3
|
||||
order.add_variant digital_variant, 2
|
||||
order.contents.add digital_variant, 2
|
||||
order.line_items.first.quantity.should == 5
|
||||
end
|
||||
end
|
||||
@@ -26,21 +26,21 @@ describe Spree::Order do
|
||||
it "should understand that all products are digital" do
|
||||
order = FactoryGirl.create(:order)
|
||||
3.times do
|
||||
order.add_variant FactoryGirl.create(:variant, :digitals => [FactoryGirl.create(:digital)])
|
||||
order.contents.add FactoryGirl.create(:variant, :digitals => [FactoryGirl.create(:digital)]), 1
|
||||
end
|
||||
order.digital?.should be_true
|
||||
order.add_variant FactoryGirl.create(:variant, :digitals => [FactoryGirl.create(:digital)]), 4
|
||||
order.contents.add FactoryGirl.create(:variant, :digitals => [FactoryGirl.create(:digital)]), 4
|
||||
order.digital?.should be_true
|
||||
end
|
||||
|
||||
it "should understand that not all products are digital" do
|
||||
order = FactoryGirl.create(:order)
|
||||
3.times do
|
||||
order.add_variant FactoryGirl.create(:variant, :digitals => [FactoryGirl.create(:digital)])
|
||||
order.contents.add FactoryGirl.create(:variant, :digitals => [FactoryGirl.create(:digital)]), 1
|
||||
end
|
||||
order.add_variant FactoryGirl.create(:variant) # this is the analog product
|
||||
order.contents.add FactoryGirl.create(:variant), 1 # this is the analog product
|
||||
order.digital?.should be_false
|
||||
order.add_variant FactoryGirl.create(:variant, :digitals => [FactoryGirl.create(:digital)]), 4
|
||||
order.contents.add FactoryGirl.create(:variant, :digitals => [FactoryGirl.create(:digital)]), 4
|
||||
order.digital?.should be_false
|
||||
end
|
||||
end
|
||||
@@ -53,7 +53,7 @@ describe Spree::Order do
|
||||
@order.bill_address = FactoryGirl.create :address
|
||||
@order.save!
|
||||
|
||||
3.times { @order.add_variant FactoryGirl.create(:variant, :digitals => [FactoryGirl.create(:digital)]) }
|
||||
3.times { @order.contents.add FactoryGirl.create(:variant, :digitals => [FactoryGirl.create(:digital)]), 1 }
|
||||
|
||||
FactoryGirl.create :digital_shipping_method
|
||||
s = FactoryGirl.create :shipping_method
|
||||
@@ -64,14 +64,15 @@ describe Spree::Order do
|
||||
|
||||
it "should only offer digital shipping if all items are digital" do
|
||||
order.digital?.should be_true
|
||||
order.rate_hash.count.should == 1
|
||||
order.rate_hash.first.shipping_method.calculator.class.should == Spree::Calculator::DigitalDelivery
|
||||
order.rate_hash.first.cost.should == 0.0
|
||||
shipments = order.create_proposed_shipments
|
||||
shipments.count.should == 1
|
||||
shipments.first.shipping_method.calculator.class.should == Spree::Calculator::DigitalDelivery
|
||||
shipments.first.cost.should == 0.0
|
||||
end
|
||||
|
||||
it "should not offer digital shipping if only some items are digital" do
|
||||
order.digital?.should be_true
|
||||
order.add_variant FactoryGirl.create(:variant) # this is the analog product
|
||||
order.contents.add FactoryGirl.create(:variant), 1 # this is the analog product
|
||||
order.digital?.should be_false
|
||||
|
||||
order.rate_hash.count.should == 1
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
ENV["RAILS_ENV"] = "test"
|
||||
require File.expand_path("../dummy/config/environment.rb", __FILE__)
|
||||
# Run Coverage report
|
||||
require 'simplecov'
|
||||
SimpleCov.start do
|
||||
add_group 'Controllers', 'app/controllers'
|
||||
add_group 'Helpers', 'app/helpers'
|
||||
add_group 'Mailers', 'app/mailers'
|
||||
add_group 'Models', 'app/models'
|
||||
add_group 'Views', 'app/views'
|
||||
add_group 'Libraries', 'lib'
|
||||
end
|
||||
|
||||
# Configure Rails Environment
|
||||
ENV['RAILS_ENV'] = 'test'
|
||||
|
||||
require File.expand_path('../dummy/config/environment.rb', __FILE__)
|
||||
|
||||
require 'rspec/rails'
|
||||
require 'database_cleaner'
|
||||
require 'ffaker'
|
||||
@@ -7,37 +21,65 @@ require 'shoulda-matchers'
|
||||
|
||||
# Requires supporting ruby files with custom matchers and macros, etc,
|
||||
# in spec/support/ and its subdirectories.
|
||||
Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].each {|f| require f }
|
||||
Dir[File.join(File.dirname(__FILE__), 'support/**/*.rb')].each { |f| require f }
|
||||
|
||||
require 'spree/core/testing_support/factories'
|
||||
require 'spree/core/testing_support/env'
|
||||
require 'spree/core/testing_support/controller_requests'
|
||||
require 'spree/core/url_helpers'
|
||||
# Requires factories defined in spree_core
|
||||
require 'spree/testing_support/factories'
|
||||
require 'spree/testing_support/controller_requests'
|
||||
require 'spree/testing_support/authorization_helpers'
|
||||
require 'spree/testing_support/url_helpers'
|
||||
|
||||
Dir[File.join(File.dirname(__FILE__), "factories/*.rb")].each {|f| require f }
|
||||
# Requires factories defined in lib/spree_digital/factories.rb
|
||||
require 'spree_digital/factories'
|
||||
|
||||
RSpec.configure do |config|
|
||||
config.mock_with :rspec
|
||||
config.include FactoryGirl::Syntax::Methods
|
||||
config.include Spree::Core::UrlHelpers
|
||||
config.include Spree::Core::TestingSupport::ControllerRequests
|
||||
|
||||
# == URL Helpers
|
||||
#
|
||||
# Allows access to Spree's routes in specs:
|
||||
#
|
||||
# visit spree.admin_path
|
||||
# current_path.should eql(spree.products_path)
|
||||
config.include Spree::TestingSupport::UrlHelpers
|
||||
|
||||
config.include Spree::TestingSupport::ControllerRequests, :type => :controller
|
||||
config.include Spree::TestingSupport::AuthorizationHelpers
|
||||
config.include Devise::TestHelpers, :type => :controller
|
||||
# == Mock Framework
|
||||
#
|
||||
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
|
||||
#
|
||||
# config.mock_with :mocha
|
||||
# config.mock_with :flexmock
|
||||
# config.mock_with :rr
|
||||
config.mock_with :rspec
|
||||
config.color = true
|
||||
|
||||
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
|
||||
config.fixture_path = "#{::Rails.root}/spec/fixtures"
|
||||
|
||||
# Capybara javascript drivers require transactional fixtures set to false, and we use DatabaseCleaner
|
||||
# to cleanup after each test instead. Without transactional fixtures set to false the records created
|
||||
# to setup a test will be unavailable to the browser, which runs under a seperate server instance.
|
||||
config.use_transactional_fixtures = false
|
||||
|
||||
config.before(:each) do
|
||||
if example.metadata[:js]
|
||||
DatabaseCleaner.strategy = :truncation, { :except => ['spree_countries', 'spree_zones', 'spree_zone_members', 'spree_states', 'spree_roles'] }
|
||||
else
|
||||
DatabaseCleaner.strategy = :transaction
|
||||
end
|
||||
# Ensure Suite is set to use transactions for speed.
|
||||
config.before :suite do
|
||||
DatabaseCleaner.strategy = :transaction
|
||||
DatabaseCleaner.clean_with :truncation
|
||||
end
|
||||
|
||||
config.before(:each) do
|
||||
# Before each spec check if it is a Javascript test and switch between using database transactions or not where necessary.
|
||||
config.before :each do
|
||||
DatabaseCleaner.strategy = example.metadata[:js] ? :truncation : :transaction
|
||||
DatabaseCleaner.start
|
||||
# reset_spree_preferences
|
||||
end
|
||||
|
||||
config.after(:each) do
|
||||
# After each spec clean the database.
|
||||
config.after :each do
|
||||
DatabaseCleaner.clean
|
||||
end
|
||||
end
|
||||
|
||||
config.fail_fast = ENV['FAIL_FAST'] || false
|
||||
end
|
||||
|
||||
@@ -1,25 +1,31 @@
|
||||
# encoding: UTF-8
|
||||
Gem::Specification.new do |s|
|
||||
s.platform = Gem::Platform::RUBY
|
||||
s.name = 'spree_digital'
|
||||
s.version = '1.1.1'
|
||||
s.summary = ''
|
||||
s.description = 'Add digital download functionality to spree'
|
||||
s.authors = ['funkensturm', 'Michael Bianco']
|
||||
s.email = ['info@cliffsidedev.com']
|
||||
s.homepage = 'http://www.funkensturm.com'
|
||||
s.files = `git ls-files`.split("\n")
|
||||
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
||||
s.platform = Gem::Platform::RUBY
|
||||
s.name = 'spree_digital'
|
||||
s.version = '2.0.0'
|
||||
s.summary = 'Digital download functionality for spree'
|
||||
s.description = 'Digital download functionality for spree'
|
||||
s.required_ruby_version = '>= 1.9.3'
|
||||
|
||||
s.author = 'Dinis Lage'
|
||||
s.email = 'dinis@senolage.com'
|
||||
s.homepage = 'http://senolage.com'
|
||||
|
||||
#s.files = `git ls-files`.split("\n")
|
||||
#s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
||||
s.require_path = 'lib'
|
||||
s.requirements << 'none'
|
||||
s.required_ruby_version = '>= 1.8.7'
|
||||
s.add_dependency 'spree_core', '>= 1.1.0'
|
||||
|
||||
# test suite
|
||||
s.add_development_dependency 'shoulda-matchers'
|
||||
s.add_development_dependency 'capybara'
|
||||
s.add_development_dependency 'factory_girl_rails', '~> 1.7.0'
|
||||
s.add_development_dependency 'rspec-rails', '~> 2.8'
|
||||
s.add_development_dependency 'sqlite3'
|
||||
s.add_development_dependency 'ffaker'
|
||||
s.add_dependency 'spree_core', '~> 2.0.0'
|
||||
|
||||
s.add_development_dependency 'capybara', '~> 2.1'
|
||||
s.add_development_dependency 'coffee-rails'
|
||||
s.add_development_dependency 'database_cleaner'
|
||||
end
|
||||
s.add_development_dependency 'factory_girl', '~> 4.2'
|
||||
s.add_development_dependency 'ffaker'
|
||||
s.add_development_dependency 'rspec-rails', '~> 2.13'
|
||||
s.add_development_dependency 'sass-rails'
|
||||
s.add_development_dependency 'selenium-webdriver'
|
||||
s.add_development_dependency 'simplecov'
|
||||
s.add_development_dependency 'sqlite3'
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user