spree_address_book 0.40.0.rc

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ \#*
2
+ *~
3
+ .#*
4
+ .DS_Store
5
+ .idea
6
+ .project
7
+ tmp
8
+ nbproject
9
+ *.swp
10
+ *.bak
11
+ spec/test_app
12
+ Gemfile
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ Redistribution and use in source and binary forms, with or without modification,
2
+ are permitted provided that the following conditions are met:
3
+
4
+ * Redistributions of source code must retain the above copyright notice,
5
+ this list of conditions and the following disclaimer.
6
+ * Redistributions in binary form must reproduce the above copyright notice,
7
+ this list of conditions and the following disclaimer in the documentation
8
+ and/or other materials provided with the distribution.
9
+ * Neither the name of the Rails Dog LLC nor the names of its
10
+ contributors may be used to endorse or promote products derived from this
11
+ software without specific prior written permission.
12
+
13
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
16
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,10 @@
1
+ SpreeAddressBook
2
+ ================
3
+
4
+ This extension allows users select `bill_address` and `ship_address` from addresses, which was already entered by current user.
5
+
6
+
7
+
8
+
9
+
10
+ Copyright (c) 2011 Roman Smirnov, released under the New BSD License
data/Rakefile ADDED
@@ -0,0 +1,77 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/packagetask'
5
+ require 'rake/gempackagetask'
6
+
7
+ gemfile = File.expand_path('../spec/test_app/Gemfile', __FILE__)
8
+ if File.exists?(gemfile) && (%w(spec cucumber).include?(ARGV.first.to_s) || ARGV.size == 0)
9
+ require 'bundler'
10
+ ENV['BUNDLE_GEMFILE'] = gemfile
11
+ Bundler.setup
12
+
13
+ require 'rspec'
14
+ require 'rspec/core/rake_task'
15
+ RSpec::Core::RakeTask.new
16
+
17
+ require 'cucumber/rake/task'
18
+ Cucumber::Rake::Task.new do |t|
19
+ t.cucumber_opts = %w{--format progress}
20
+ end
21
+ end
22
+
23
+ desc "Default Task"
24
+ task :default => [:spec, :cucumber ]
25
+
26
+ spec = eval(File.read('spree_address_book.gemspec'))
27
+
28
+ Rake::GemPackageTask.new(spec) do |p|
29
+ p.gem_spec = spec
30
+ end
31
+
32
+ desc "Release to gemcutter"
33
+ task :release => :package do
34
+ require 'rake/gemcutter'
35
+ Rake::Gemcutter::Tasks.new(spec).define
36
+ Rake::Task['gem:push'].invoke
37
+ end
38
+
39
+ desc "Default Task"
40
+ task :default => [ :spec ]
41
+
42
+ desc "Regenerates a rails 3 app for testing"
43
+ task :test_app do
44
+ require '../spree/lib/generators/spree/test_app_generator'
45
+ class AddressBookTestAppGenerator < Spree::Generators::TestAppGenerator
46
+
47
+ def install_gems
48
+ inside "test_app" do
49
+ run 'rake spree_core:install'
50
+ run 'rake spree_auth:install'
51
+ run 'rake spree_address_book:install'
52
+ end
53
+ end
54
+
55
+ def migrate_db
56
+ run_migrations
57
+ end
58
+
59
+ protected
60
+ def full_path_for_local_gems
61
+ <<-gems
62
+ gem 'spree_core', :path => \'#{File.join(File.dirname(__FILE__), "../spree/", "core")}\'
63
+ gem 'spree_auth', :path => \'#{File.join(File.dirname(__FILE__), "../spree/", "auth")}\'
64
+ gem 'spree_address_book', :path => \'#{File.dirname(__FILE__)}\'
65
+ gems
66
+ end
67
+
68
+ end
69
+ AddressBookTestAppGenerator.start
70
+ end
71
+
72
+ namespace :test_app do
73
+ desc 'Rebuild test and cucumber databases'
74
+ task :rebuild_dbs do
75
+ system("cd spec/test_app && rake db:drop db:migrate RAILS_ENV=test && rake db:drop db:migrate RAILS_ENV=cucumber")
76
+ end
77
+ end
@@ -0,0 +1,12 @@
1
+ class AddressesController < Spree::BaseController
2
+ def destroy
3
+ @address = Address.find(params[:id])
4
+ if @address && @address.user == current_user
5
+ if @address.can_be_deleted?
6
+ @address.destroy
7
+ else
8
+ @address.update_attribute(:deleted_at, Time.now)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,35 @@
1
+ CheckoutController.class_eval do
2
+ after_filter :normalize_addresses, :only => :update
3
+ before_filter :set_addresses, :only => :update
4
+
5
+ protected
6
+
7
+ def set_addresses
8
+ return unless params[:order] && params[:state] == "address"
9
+
10
+ if params[:order][:ship_address_id].to_i > 0
11
+ params[:order].delete(:ship_address_attributes)
12
+ else
13
+ params[:order].delete(:ship_address_id)
14
+ end
15
+
16
+ if params[:order][:bill_address_id].to_i > 0
17
+ params[:order].delete(:bill_address_attributes)
18
+ else
19
+ params[:order].delete(:bill_address_id)
20
+ end
21
+ end
22
+
23
+ def normalize_addresses
24
+ return unless params[:state] == "address" && @order.bill_address_id && @order.ship_address_id
25
+ @order.bill_address.reload
26
+ @order.ship_address.reload
27
+ if @order.bill_address_id != @order.ship_address_id && @order.bill_address.same_as?(@order.ship_address)
28
+ @order.bill_address.destroy
29
+ @order.update_attribute(:bill_address_id, @order.ship_address.id)
30
+ else
31
+ @order.bill_address.update_attribute(:user_id, current_user.try(:id))
32
+ end
33
+ @order.ship_address.update_attribute(:user_id, current_user.try(:id))
34
+ end
35
+ end
@@ -0,0 +1,26 @@
1
+ Address.class_eval do
2
+ belongs_to :user
3
+
4
+ # can modify an address if it's not been used in an order
5
+ def editable?
6
+ new_record? || (shipments.empty? && (Order.where("bill_address_id = ?", self.id).count + Order.where("bill_address_id = ?", self.id).count <= 1) && Order.complete.where("bill_address_id = ? OR ship_address_id = ?", self.id, self.id).count == 0)
7
+ end
8
+
9
+ def can_be_deleted?
10
+ shipments.empty? && Order.where("bill_address_id = ? OR ship_address_id = ?", self.id, self.id).count == 0
11
+ end
12
+
13
+ def to_s
14
+ "#{firstname} #{lastname}: #{zipcode}, #{country}, #{state || state_name}, #{city}, #{address1} #{address2}"
15
+ end
16
+
17
+ def destroy_with_saving_used
18
+ if can_be_deleted?
19
+ destroy_without_saving_used
20
+ else
21
+ update_attribute(:deleted_at, Time.now)
22
+ end
23
+ end
24
+ alias_method_chain :destroy, :saving_used
25
+
26
+ end
@@ -0,0 +1,60 @@
1
+ Order.class_eval do
2
+ attr_accessible :bill_address_id, :ship_address_id
3
+
4
+ def clone_billing_address
5
+ if self.bill_address
6
+ self.ship_address = self.bill_address
7
+ end
8
+ true
9
+ end
10
+
11
+ def bill_address_id=(id)
12
+ address = Address.find(id)
13
+ if address && address.user_id == self.user_id
14
+ self["bill_address_id"] = address.id
15
+ self.bill_address.reload
16
+ else
17
+ self["bill_address_id"] = nil
18
+ end
19
+ end
20
+
21
+ def bill_address_attributes=(attributes)
22
+ self.bill_address = update_or_create_address(attributes)
23
+ end
24
+
25
+ def ship_address_id=(id)
26
+ address = Address.find(id)
27
+ if address && address.user_id == self.user_id
28
+ self["ship_address_id"] = address.id
29
+ self.ship_address.reload
30
+ else
31
+ self["ship_address_id"] = nil
32
+ end
33
+ end
34
+
35
+ def ship_address_attributes=(attributes)
36
+ self.ship_address = update_or_create_address(attributes)
37
+ end
38
+
39
+ private
40
+
41
+ def update_or_create_address(attributes)
42
+ address = nil
43
+ if attributes[:id]
44
+ address = Address.find(attributes[:id])
45
+ if address && address.editable?
46
+ address.update_attributes(attributes)
47
+ else
48
+ attributes.delete(:id)
49
+ end
50
+ end
51
+
52
+ if !attributes[:id]
53
+ address = Address.new(attributes)
54
+ address.save
55
+ end
56
+
57
+ address
58
+ end
59
+
60
+ end
@@ -0,0 +1,3 @@
1
+ User.class_eval do
2
+ has_many :addresses, :conditions => {:deleted_at => nil}
3
+ end
@@ -0,0 +1,46 @@
1
+ <% ADDRESS_FIELDS.each do |field| %>
2
+ <p id="<%= [address_name, field].join('_') %>" class="field">
3
+ <% if field == "country" %>
4
+ <%= address_form.label :country_id, t(field, :scope => [:activerecord, :attributes, :address]) %>
5
+ <span><%= address_form.collection_select :country_id, available_countries, :id, :name, {}, {:class => 'required'} %></span>
6
+ <span class="req">*</span>
7
+ <% elsif field == "state" && Spree::Config[:address_requires_state] %>
8
+ <%= address_form.label :state_id, t(field, :scope => [:activerecord, :attributes, :address]) %>
9
+ <span id="state">
10
+ <% have_states = !address.country.states.empty? %>
11
+ <noscript>
12
+ <%= address_form.text_field :state_name, :class => 'required' %>
13
+ </noscript>
14
+ <% state_elements = [
15
+ address_form.collection_select(:state_id, address.country.states,
16
+ :id, :name,
17
+ {:include_blank => true},
18
+ {:class => have_states ? "required" : "hidden",
19
+ :disabled => !have_states}) +
20
+ address_form.text_field(:state_name,
21
+ :class => !have_states ? "required" : "hidden",
22
+ :disabled => have_states)
23
+ ].join.gsub('"', "'").gsub("\n", "")
24
+ %>
25
+ <script type="text/javascript" language="javascript" charset="utf-8">
26
+ // <![CDATA[
27
+ document.write("<%= raw state_elements %>");
28
+ // ]]>
29
+ </script>
30
+ </span>
31
+ <span class="req">*</span>
32
+ <% elsif field == "address2" %>
33
+ <%= address_form.label field, t(field, :scope => [:activerecord, :attributes, :address]) %>
34
+ <%= address_form.text_field field %>
35
+ <% else %>
36
+ <%= address_form.label field, t(field, :scope => [:activerecord, :attributes, :address]) %>
37
+ <%= address_form.text_field field, :class => 'required' %><span class="req">*</span>
38
+ <% end %>
39
+ </p>
40
+ <% end %>
41
+ <% if Spree::Config["alternative_#{address_name}_phone"] %>
42
+ <p id="altphone">
43
+ <%= address_form.label :alternative_phone, t(:alternative_phone) %>
44
+ <%= address_form.text_field :alternative_phone %>
45
+ </p>
46
+ <% end %>
@@ -0,0 +1,2 @@
1
+ $("#billing_address_<%= @address.id %>").fadeOut();
2
+ $("#shipping_address_<%= @address.id %>").fadeOut();
@@ -0,0 +1,82 @@
1
+ <% @addresses = current_user ? current_user.addresses : [] %>
2
+ <style>
3
+ div.inner input[type=text], div.inner select { width: 80%; }
4
+ .hidden { display: none; }
5
+ div#checkout #checkout_form_address #billing .select_address label { float:none; }
6
+ div#checkout #checkout_form_address #shipping .select_address label { float:none; }
7
+ </style>
8
+
9
+ <% ['billing', 'shipping'].each do |address_type| %>
10
+ <% address_name = "#{address_type[0...4]}_address" %>
11
+ <fieldset id="<%= address_type %>">
12
+ <legend><%= t(address_type + "_address")%></legend>
13
+ <% if address_type == 'shipping' %>
14
+ <p class="field checkbox">
15
+ <label for="order_use_billing" id="use_billing">
16
+ <%= check_box_tag 'order[use_billing]', '1', (!(@order.bill_address.empty? && @order.ship_address.empty?) && @order.bill_address.eql?(@order.ship_address)) %> <%= t("use_billing_address") %>
17
+ </label>
18
+ </p>
19
+ <% end %>
20
+ <div class="select_address">
21
+ <p class="field">
22
+ <% if @addresses.present? %>
23
+ <% @addresses.each do |address| %>
24
+ <span id="<%= [address_type, dom_id(address)].join('_') %>">
25
+ <label><%= form.radio_button "#{address_name}_id", address.id %> <%= address %></label> <%= link_to t(:remove), address, :method => :delete, :remote => true %><br />
26
+ </span>
27
+ <% end %>
28
+ <label><%= form.radio_button "#{address_name}_id", 0 %> <%= t('other_address') %></label>
29
+ <% end %>
30
+ </p>
31
+ </div>
32
+ <%= form.fields_for address_name do |address_form| %>
33
+ <div class="inner">
34
+ <p class="field">&nbsp;</p>
35
+ <%= render :partial => 'addresses/form', :locals => {
36
+ :address_name => address_name,
37
+ :address_form => address_form,
38
+ :address => @order.send(address_name)
39
+ } %>
40
+ </div>
41
+ <% end %>
42
+ </fieldset>
43
+ <% end %>
44
+
45
+ <hr class="space" />
46
+ <div class="form-buttons">
47
+ <input type="submit" class="continue button primary" value="<%=t("save_and_continue") %>" />
48
+ </div>
49
+ <% if @addresses.present? %>
50
+ <%= javascript_tag do %>
51
+ $(document).ready(function(){
52
+ $(".inner input").attr('disabled', 'disabled');
53
+ $(".inner select").attr('disabled', 'disabled');
54
+ $(".inner").hide();
55
+
56
+ $("input[name='order[bill_address_id]']:radio").change(function(){
57
+ if ($("input[name='order[bill_address_id]']:checked").val() == '0') {
58
+ $("#billing .inner input").removeAttr('disabled');
59
+ $("#billing .inner select").removeAttr('disabled');
60
+ $("#billing .inner").fadeIn();
61
+ } else {
62
+ $("#billing .inner input").attr('disabled', 'disabled');
63
+ $("#billing .inner select").attr('disabled', 'disabled');
64
+ $("#billing .inner").fadeOut();
65
+ }
66
+ });
67
+
68
+ $("input[name='order[ship_address_id]']:radio").change(function(){
69
+ if ($("input[name='order[ship_address_id]']:checked").val() == '0') {
70
+ $("#shipping .inner input").removeAttr('disabled');
71
+ $("#shipping .inner select").removeAttr('disabled');
72
+ $("#shipping .inner").fadeIn();
73
+ } else {
74
+ $("#shipping .inner input").attr('disabled', 'disabled');
75
+ $("#shipping .inner select").attr('disabled', 'disabled');
76
+ $("#shipping .inner").fadeOut();
77
+ }
78
+ });
79
+
80
+ });
81
+ <% end %>
82
+ <% end %>
@@ -0,0 +1 @@
1
+ ADDRESS_FIELDS = ["firstname", "lastname", "address1", "address2", "city", "state", "zipcode", "country", "phone"]
@@ -0,0 +1,2 @@
1
+ en:
2
+ other_address: "Other address"
@@ -0,0 +1,2 @@
1
+ ru:
2
+ other_address: "Другой адрес"
data/config/routes.rb ADDED
@@ -0,0 +1,3 @@
1
+ Rails.application.routes.draw do
2
+ resources :addresses, :only => [:edit, :update, :destroy]
3
+ end
@@ -0,0 +1,15 @@
1
+ class AddUserIdAndDeletedAtToAddresses < ActiveRecord::Migration
2
+ def self.up
3
+ change_table :addresses do |t|
4
+ t.integer :user_id
5
+ t.datetime :deleted_at
6
+ end
7
+ end
8
+
9
+ def self.down
10
+ change_table :addresses do |t|
11
+ t.remove :deleted_at
12
+ t.remove :user_id
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,70 @@
1
+ Feature: Address Book
2
+
3
+ @selenium @wip @stop
4
+ Scenario: User fill new address
5
+ Given an order from registered user "email@person.com/password", who has 0 addresses, at address step
6
+ When I fill billing address with correct data
7
+ And check "order_use_billing"
8
+ And press "Save and Continue"
9
+ Then user "email@person.com" should have 1 address
10
+ When I choose "UPS Ground" as shipping method and "Check" as payment method
11
+ Then I should see "Your order has been processed successfully"
12
+
13
+ @selenium @wip @stop
14
+ Scenario: User select address
15
+ Given an order from registered user "email@person.com/password", who has 1 addresses, at address step
16
+ When I choose "order_bill_address_id_1"
17
+ And I choose "order_ship_address_id_1"
18
+ And press "Save and Continue"
19
+ Then user "email@person.com" should have 1 address
20
+ When I choose "UPS Ground" as shipping method and "Check" as payment method
21
+ Then I should see "Your order has been processed successfully"
22
+
23
+ @selenium @wip @stop
24
+ Scenario: User select address
25
+ Given an order from registered user "email@person.com/password", who has 1 addresses, at address step
26
+ When I choose "order_bill_address_id_1"
27
+ And check "order_use_billing"
28
+ And press "Save and Continue"
29
+ Then user "email@person.com" should have 1 address
30
+ When I choose "UPS Ground" as shipping method and "Check" as payment method
31
+ Then I should see "Your order has been processed successfully"
32
+
33
+ @selenium @wip @stop
34
+ Scenario: User select address
35
+ Given an order from registered user "email@person.com/password", who has 1 addresses, at address step
36
+ When I choose "order_bill_address_id_0"
37
+ And I fill billing address with correct data
38
+ And I choose "order_ship_address_id_0"
39
+ And I fill shipping address with correct data
40
+ And press "Save and Continue"
41
+ Then user "email@person.com" should have 2 address
42
+ When I choose "UPS Ground" as shipping method and "Check" as payment method
43
+ Then I should see "Your order has been processed successfully"
44
+
45
+ @selenium @wip @stop
46
+ Scenario: User select address
47
+ Given an order from registered user "email@person.com/password", who has 1 addresses, at address step
48
+ When I choose "order_bill_address_id_0"
49
+ And I fill billing address with correct data
50
+ And I check "order_use_billing"
51
+ And press "Save and Continue"
52
+ Then user "email@person.com" should have 2 address
53
+ When I choose "UPS Ground" as shipping method and "Check" as payment method
54
+ Then I should see "Your order has been processed successfully"
55
+
56
+ @selenium @wip @stop
57
+ Scenario: User can edit address, if it was not used by another order
58
+ Given an order from registered user "email@person.com/password", who has 1 addresses, at address step
59
+ When I choose "order_bill_address_id_1"
60
+ And I choose "order_ship_address_id_1"
61
+ And press "Save and Continue"
62
+ Then user "email@person.com" should have 1 address
63
+ When I follow "Address"
64
+ Then I should see "10 Lovely Street Northwest"
65
+ When I choose "order_bill_address_id_0"
66
+ And fill in "order_bill_address_attributes_zipcode" with "125000"
67
+ And press "Save and Continue"
68
+ Then user "email@person.com" should have 2 address
69
+ When I choose "UPS Ground" as shipping method and "Check" as payment method
70
+ Then I should see "Your order has been processed successfully"
@@ -0,0 +1,21 @@
1
+ Given /^an order from registered user "([^"]*)", who has (\d+) addresses, at address step$/ do |user_data, addresses_count|
2
+ Given "a shipping method exists"
3
+ Given "a payment method exists"
4
+ Given "I am signed up as \"#{user_data}\""
5
+ Given "user \"#{user_data}\" has #{addresses_count} addresses"
6
+ Given "I add a product with name: \"RoR Mug\" to cart"
7
+ Given "I follow \"Checkout\""
8
+ Given "I sign in as \"email@person.com/password\""
9
+ end
10
+
11
+ Then /^user "([^"]*)" should have (\d+) address$/ do |email, count|
12
+ User.find_by_email(email).addresses.count.should == count.to_i
13
+ end
14
+
15
+ Given /^user "([^"]*)" has (\d+) addresses$/ do |user_data, count|
16
+ user = User.find_by_email(user_data.split('/')[0])
17
+ state = State.first
18
+ count.to_i.times do
19
+ Factory(:address, :state => state, :user => user)
20
+ end
21
+ end
@@ -0,0 +1,22 @@
1
+ FEATURES_PATH = File.expand_path('../..', __FILE__)
2
+
3
+ # load shared env with features
4
+ require File.expand_path('../../../../spree/features/support/env', __FILE__)
5
+
6
+ # load the rest of files for support and step definitions
7
+ directories = [ File.expand_path('../../../../spree/features/support', __FILE__),
8
+ File.expand_path('../../../../spree/features/step_definitions', __FILE__),
9
+ File.expand_path('../../../spec/factories', __FILE__) ]
10
+
11
+ files = directories.map do |dir|
12
+ Dir["#{dir}/**/*.rb"]
13
+ end.flatten.uniq
14
+
15
+ files.each do |path|
16
+ if path !~ /env.rb$/
17
+ fp = File.expand_path(path)
18
+ #puts fp
19
+ load(fp)
20
+ end
21
+ end
22
+
@@ -0,0 +1,40 @@
1
+ module NavigationHelpers
2
+ # Maps a name to a path. Used by the
3
+ #
4
+ # When /^I go to (.+)$/ do |page_name|
5
+ #
6
+ # step definition in web_steps.rb
7
+ #
8
+ def path_to(page_name)
9
+ case page_name
10
+
11
+ when "admin promotions page"
12
+ admin_promotions_path
13
+ when /the home\s?page/
14
+ '/'
15
+ when /the sign in page/
16
+ new_user_session_path
17
+ when /the sign up page/
18
+ new_user_registration_path
19
+
20
+ # Add more mappings here.
21
+ # Here is an example that pulls values out of the Regexp:
22
+ #
23
+ # when /^(.*)'s profile page$/i
24
+ # user_profile_path(User.find_by_login($1))
25
+
26
+ else
27
+ begin
28
+ page_name =~ /the (.*) page/
29
+ path_components = $1.split(/\s+/)
30
+ self.send(path_components.push('path').join('_').to_sym)
31
+ rescue Object => e
32
+ raise "Can't find mapping from \"#{page_name}\" to a path.\n" +
33
+ "Now, go and add a mapping in #{__FILE__}"
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ World(NavigationHelpers)
40
+
@@ -0,0 +1,17 @@
1
+ require 'spree_core'
2
+ require 'spree_address_book_hooks'
3
+
4
+ module SpreeAddressBook
5
+ class Engine < Rails::Engine
6
+
7
+ config.autoload_paths += %W(#{config.root}/lib)
8
+
9
+ def self.activate
10
+ Dir.glob(File.join(File.dirname(__FILE__), "../app/**/*_decorator*.rb")) do |c|
11
+ Rails.env.production? ? require(c) : load(c)
12
+ end
13
+ end
14
+
15
+ config.to_prepare &method(:activate).to_proc
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ class SpreeAddressBookHooks < Spree::ThemeSupport::HookListener
2
+ # custom hooks go here
3
+ end
@@ -0,0 +1,25 @@
1
+ namespace :spree_address_book do
2
+ desc "Copies all migrations and assets (NOTE: This will be obsolete with Rails 3.1)"
3
+ task :install do
4
+ Rake::Task['spree_address_book:install:migrations'].invoke
5
+ Rake::Task['spree_address_book:install:assets'].invoke
6
+ end
7
+
8
+ namespace :install do
9
+ desc "Copies all migrations (NOTE: This will be obsolete with Rails 3.1)"
10
+ task :migrations do
11
+ source = File.join(File.dirname(__FILE__), '..', '..', 'db')
12
+ destination = File.join(Rails.root, 'db')
13
+ Spree::FileUtilz.mirror_files(source, destination)
14
+ end
15
+
16
+ desc "Copies all assets (NOTE: This will be obsolete with Rails 3.1)"
17
+ task :assets do
18
+ source = File.join(File.dirname(__FILE__), '..', '..', 'public')
19
+ destination = File.join(Rails.root, 'public')
20
+ puts "INFO: Mirroring assets from #{source} to #{destination}"
21
+ Spree::FileUtilz.mirror_files(source, destination)
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1 @@
1
+ # add custom rake tasks here
@@ -0,0 +1,73 @@
1
+ (function($){
2
+ $(document).ready(function(){
3
+
4
+ $('#checkout_form_address').validate();
5
+
6
+ var get_states = function(region){
7
+ var country = $('p#' + region + 'country' + ' span#' + region + 'country :only-child').val();
8
+ return state_mapper[country];
9
+ }
10
+
11
+ var update_state = function(region) {
12
+ var states = get_states(region);
13
+
14
+ var state_select = $('span#' + region + 'state select');
15
+ var state_input = $('span#' + region + 'state input');
16
+
17
+ if(states) {
18
+ var selected = state_select.val();
19
+ state_select.html('');
20
+ var states_with_blank = [["",""]].concat(states);
21
+ $.each(states_with_blank, function(pos,id_nm) {
22
+ var opt = $(document.createElement('option'))
23
+ .attr('value', id_nm[0])
24
+ .html(id_nm[1]);
25
+ if(selected==id_nm[0]){
26
+ opt.attr('selected', 'selected');
27
+ }
28
+ state_select.append(opt);
29
+ });
30
+ state_select.removeAttr('disabled').show();
31
+ state_input.hide().attr('disabled', 'disabled');
32
+
33
+ } else {
34
+ state_input.removeAttr('disabled').show();
35
+ state_select.hide().attr('disabled', 'disabled');
36
+ }
37
+
38
+ };
39
+
40
+ // Show fields for the selected payment method
41
+ $("input[type='radio'][name='order[payments_attributes][][payment_method_id]']").click(function(){
42
+ $('#payment-methods li').hide();
43
+ if(this.checked){ $('#payment_method_'+this.value).show(); }
44
+ }).triggerHandler('click');
45
+
46
+ $('p#bcountry span#bcountry select').change(function() { update_state('b'); });
47
+ $('p#scountry span#scountry select').change(function() { update_state('s'); });
48
+ update_state('b');
49
+ update_state('s');
50
+
51
+ $('input#order_use_billing').click(function() {
52
+ if($(this).is(':checked')) {
53
+ $("#shipping .inner input").attr('disabled', 'disabled');
54
+ $("#shipping .inner select").attr('disabled', 'disabled');
55
+ $("#shipping .inner").fadeOut();
56
+ $("#shipping .select_address").fadeOut();
57
+ } else {
58
+ if ($("input[name='order[ship_address_id]']:checked").val() == '0') {
59
+ $("#shipping .inner input").removeAttr('disabled');
60
+ $("#shipping .inner select").removeAttr('disabled');
61
+ $("#shipping .inner").fadeIn();
62
+ }
63
+ $("#shipping .select_address").fadeIn();
64
+ }
65
+ }).triggerHandler('click');
66
+
67
+ $('form.edit_checkout').submit(function() {
68
+ $(this).find(':submit, :image').attr('disabled', true).removeClass('primary').addClass('disabled');
69
+ });
70
+
71
+
72
+ });
73
+ })(jQuery);
@@ -0,0 +1,5 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Address do
4
+
5
+ end
@@ -0,0 +1,32 @@
1
+ # This file is copied to ~/spec when you run 'ruby script/generate rspec'
2
+ # from the project root directory.
3
+ ENV["RAILS_ENV"] ||= 'test'
4
+ require File.expand_path("../test_app/config/environment", __FILE__)
5
+ require 'rspec/rails'
6
+
7
+ # Requires supporting files with custom matchers and macros, etc,
8
+ # in ./support/ and its subdirectories.
9
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
10
+
11
+ require 'spree_core/testing_support/factories'
12
+
13
+ RSpec.configure do |config|
14
+ # == Mock Framework
15
+ #
16
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
17
+ #
18
+ # config.mock_with :mocha
19
+ # config.mock_with :flexmock
20
+ # config.mock_with :rr
21
+ config.mock_with :rspec
22
+
23
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
24
+
25
+ #config.include Devise::TestHelpers, :type => :controller
26
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
27
+ # examples within a transaction, comment the following line or assign false
28
+ # instead of true.
29
+ config.use_transactional_fixtures = true
30
+ end
31
+
32
+ @configuration ||= AppConfiguration.find_or_create_by_name("Default configuration")
@@ -0,0 +1,23 @@
1
+ Gem::Specification.new do |s|
2
+ s.platform = Gem::Platform::RUBY
3
+ s.name = 'spree_address_book'
4
+ s.version = '0.40.0.rc'
5
+ s.summary = 'Adds address book for users to Spree'
6
+ #s.description = 'Add (optional) gem description here'
7
+ s.required_ruby_version = '>= 1.8.7'
8
+
9
+ s.author = 'Roman Smirnov'
10
+ s.email = 'roman@railsdog.com'
11
+ s.homepage = 'http://github.com/romul/spree_address_book'
12
+ # s.rubyforge_project = 'actionmailer'
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.require_path = 'lib'
17
+ s.requirements << 'none'
18
+
19
+ s.has_rdoc = true
20
+
21
+ s.add_dependency('spree_core', '>= 0.40.0')
22
+ s.add_dependency('spree_auth', '>= 0.40.0')
23
+ end
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spree_address_book
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: true
5
+ segments:
6
+ - 0
7
+ - 40
8
+ - 0
9
+ - rc
10
+ version: 0.40.0.rc
11
+ platform: ruby
12
+ authors:
13
+ - Roman Smirnov
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-03-08 00:00:00 +03:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: spree_core
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ - 40
31
+ - 0
32
+ version: 0.40.0
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: spree_auth
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 0
44
+ - 40
45
+ - 0
46
+ version: 0.40.0
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ description:
50
+ email: roman@railsdog.com
51
+ executables: []
52
+
53
+ extensions: []
54
+
55
+ extra_rdoc_files: []
56
+
57
+ files:
58
+ - .gitignore
59
+ - LICENSE
60
+ - README.md
61
+ - Rakefile
62
+ - app/controllers/addresses_controller.rb
63
+ - app/controllers/checkout_controller_decorator.rb
64
+ - app/models/address_decorator.rb
65
+ - app/models/order_decorator.rb
66
+ - app/models/user_decorator.rb
67
+ - app/views/addresses/_form.html.erb
68
+ - app/views/addresses/destroy.js.erb
69
+ - app/views/checkout/_address.html.erb
70
+ - config/initializers/address_fields.rb
71
+ - config/locales/en.yml
72
+ - config/locales/ru.yml
73
+ - config/routes.rb
74
+ - db/migrate/20110302102208_add_user_id_and_deleted_at_to_addresses.rb
75
+ - features/address_book.feature
76
+ - features/step_definitions/address_book_steps.rb
77
+ - features/support/env.rb
78
+ - features/support/paths.rb
79
+ - lib/spree_address_book.rb
80
+ - lib/spree_address_book_hooks.rb
81
+ - lib/tasks/install.rake
82
+ - lib/tasks/spree_address_book.rake
83
+ - public/javascripts/checkout.js
84
+ - spec/models/address_spec.rb
85
+ - spec/spec_helper.rb
86
+ - spree_address_book.gemspec
87
+ has_rdoc: true
88
+ homepage: http://github.com/romul/spree_address_book
89
+ licenses: []
90
+
91
+ post_install_message:
92
+ rdoc_options: []
93
+
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ segments:
101
+ - 1
102
+ - 8
103
+ - 7
104
+ version: 1.8.7
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">"
108
+ - !ruby/object:Gem::Version
109
+ segments:
110
+ - 1
111
+ - 3
112
+ - 1
113
+ version: 1.3.1
114
+ requirements:
115
+ - none
116
+ rubyforge_project:
117
+ rubygems_version: 1.3.6
118
+ signing_key:
119
+ specification_version: 3
120
+ summary: Adds address book for users to Spree
121
+ test_files: []
122
+