我面临以下问题:
ActionController::RoutingError (未初始化常量 Spree::Api::AramexAddressController::AramexAddressValidator):
app/controllers/spree/api/aramex_address_controller.rb:2:in<class:AramexAddressController>
app/controllers/spree/api/aramex_address_controller.rb:1:in<top (required)>
我在我的controllers/spree/api/aramex_address_controller.rb中包含了以下内容:
class Spree::Api::AramexAddressController < ApplicationController
include AramexAddressValidator
# fetch cities from aramex api
def fetch_cities_from_aramex_address
response = []
zones = Spree::ShippingMethod.where(['LOWER(admin_name) like ?', '%aramex%']).map(&:zones).flatten
if zones.map(&:countries).flatten.map(&:iso).include?(params['country_code'])
response = JSON.parse(fetch_cities(params['country_code']))['Cities']
end
respond_to do |format|
format.json { render :json => response, :status => 200 }
end
end
# Validate address for aramex shipping
def validate_address_with_aramex
begin
zones = Spree::ShippingMethod.where(['LOWER(admin_name) like ?', '%aramex%']).map(&:zones).flatten
final_response = {}
if zones.map(&:countries).flatten.map(&:iso).include?(params[:b_country])
final_response[:b_errors] = confirm_address_validity(params[:b_city], params[:b_zipcode], params[:b_country])
end
if zones.map(&:countries).flatten.map(&:iso).include?(params[:s_country]) && params[:use_bill_address] == "false"
final_response[:s_errors] = confirm_address_validity(params[:s_city], params[:s_zipcode], params[:s_country])
end
rescue
return true
end
respond_to do |format|
format.json { render :json => final_response, :status => 200 }
end
end
# Confirm address validity with Aramex address validatio API
def confirm_address_validity(city, zipcode, country)
response = JSON.parse(validate_address(city, zipcode, country))
if response['HasErrors'] == true
if response['SuggestedAddresses'].present?
response['Notifications'].map{|data| data['Message']}.join(', ') + ', Suggested city name is - ' + response['SuggestedAddresses'].map{|data| data['City']}.join(', ')
else
if response['Notifications'].first['Code'] == 'ERR06'
response['Notifications'].map{|data| data['Message']}.join(', ')
else
cities_response = JSON.parse(fetch_cities(country, city[0..2]))
cities_response['Notifications'].map{|data| data['Message']}.join(', ') + ', Suggested city name is - ' + cities_response['Cities'].join(' ,')
end
end
end
end
end
在我的路线文件中,我提到了:
get 'validate_address_with_aramex', to: 'aramex_address#validate_address_with_aramex'
get 'fetch_cities_from_aramex_address', to: 'aramex_address#fetch_cities_from_aramex_address'
我在assets/javascripts/spree/frontend/checkout/address.js中包含了以下 JS 调用,用于提交的 Aramex Ajax 验证:
Spree.ready(function($) {
Spree.onAddress = function() {
var call_aramex = true;
$("#checkout_form_address").on('submit', function(e) {
if ($('#checkout_form_address').valid()) {
var s_country = $("#order_ship_address_attributes_country_id").find('option:selected').attr('iso_code');
var s_zipcode = $("#order_ship_address_attributes_zipcode").val();
var s_city = $("#order_ship_address_attributes_city").val();
var b_country = $("#order_bill_address_attributes_country_id").find('option:selected').attr('iso_code');
var b_zipcode = $("#order_bill_address_attributes_zipcode").val();
var b_city = $("#order_bill_address_attributes_city").val();
if (call_aramex == true && (typeof aramex_countries !== 'undefined') && (aramex_countries.includes(b_country) || aramex_countries.includes(s_country))) {
e.preventDefault();
var error_id = $('#errorExplanation').is(':visible') ? '#errorExplanation' : '#manual_error'
$(error_id).html("").hide()
$.blockUI({
message: '<img src="/assets/ajax-loader.gif" />'
});
$.ajax({
url: "/api/validate_address_with_aramex",
type: 'GET',
dataType: "json",
data: {
s_country: s_country,
s_zipcode: s_zipcode,
s_city: s_city,
b_country: b_country,
b_zipcode: b_zipcode,
b_city: b_city,
use_bill_address: ($("#order_use_billing").is(":checked"))
},
success: function(result) {
$.unblockUI()
if (result.b_errors || result.s_errors) {
if (result.b_errors) {
$(error_id).append('<div>Billing Address ' + result.b_errors + ' </div>')
}
if (result.s_errors) {
$(error_id).append('<div>Shipping Address ' + result.s_errors + ' </div>')
}
if ((result.b_errors && !result.s_errors) && ($("#order_use_billing").is(":unchecked"))) {
$(".js-summary-edit").trigger("click")
}
$(error_id).show();
$('html, body').animate({
scrollTop: '0px'
}, 300);
} else {
call_aramex = false;
$('#checkout_form_address').submit()
}
},
error: function(xhr, status, error) {
$(error_id).append('Oops Something Went Wrong but you can process order')
$(error_id).show();
$.unblockUI()
$('html, body').animate({
scrollTop: '0px'
}, 300);
$('#checkout_form_address').submit()
}
});
}
}
})
var getCountryId, order_use_billing, update_shipping_form_state;
if (($('#checkout_form_address')).is('*')) {
($('#checkout_form_address')).validate({
rules: {
"order[bill_address_attributes][city]": {
required: true,
maxlength: function(element) {
return maxCharLimit($("#order_bill_address_attributes_country_id").val(), 22)
}
},
"order[bill_address_attributes][firstname]": {
required: true,
maxlength: function(element) {
return maxCharLimit($("#order_bill_address_attributes_country_id").val(), 15)
}
},
"order[bill_address_attributes][lastname]": {
required: true,
maxlength: function(element) {
return maxCharLimit($("#order_bill_address_attributes_country_id").val(), 17)
}
},
"order[bill_address_attributes][address1]": {
required: true,
maxlength: function(element) {
return maxCharLimit($("#order_bill_address_attributes_country_id").val(), 32)
}
},
"order[bill_address_attributes][address2]": {
maxlength: function(element) {
return maxCharLimit($("#order_bill_address_attributes_country_id").val(), 32)
}
},
"order[bill_address_attributes][zipcode]": {
maxlength: function(element) {
return maxCharLimit($("#order_bill_address_attributes_country_id").val(), 10)
}
},
"order[ship_address_attributes][city]": {
required: true,
maxlength: function(element) {
return maxCharLimit($("#order_ship_address_attributes_country_id").val(), 22)
}
},
"order[ship_address_attributes][firstname]": {
required: true,
maxlength: function(element) {
return maxCharLimit($("#order_ship_address_attributes_country_id").val(), 15)
}
},
"order[ship_address_attributes][lastname]": {
required: true,
maxlength: function(element) {
return maxCharLimit($("#order_ship_address_attributes_country_id").val(), 17)
}
},
"order[ship_address_attributes][address1]": {
required: true,
maxlength: function(element) {
return maxCharLimit($("#order_ship_address_attributes_country_id").val(), 32)
}
},
"order[ship_address_attributes][address2]": {
maxlength: function(element) {
return maxCharLimit($("#order_ship_address_attributes_country_id").val(), 32)
}
},
"order[ship_address_attributes][zipcode]": {
maxlength: function(element) {
return maxCharLimit($("#order_ship_address_attributes_country_id").val(), 10)
}
}
}
});
getCountryId = function(region) {
return $('#' + region + 'country select').val();
};
isCountryUsOrCa = function(country_id) {
return ["38", "232"].includes(country_id)
}
maxCharLimit = function(country_id, limit) {
if (["38", "232"].includes(country_id)) {
return limit;
} else {
return 255;
}
};
Spree.updateState = function(region) {
var countryId;
var cityId
countryId = getCountryId(region);
if (countryId != null) {
if (region == 'b') {
cityId = '#order_bill_address_attributes_city'
countryInputId = "#order_bill_address_attributes_country_id"
} else {
cityId = '#order_ship_address_attributes_city'
countryInputId = "#order_ship_address_attributes_country_id"
}
fill_cities($(countryInputId).find('option:selected').attr('iso_code'), cityId)
if (Spree.Checkout[countryId] == null) {
return $.get(Spree.routes.states_search, {
country_id: countryId
}, function(data) {
Spree.Checkout[countryId] = {
states: data.states,
states_required: data.states_required
};
return Spree.fillStates(Spree.Checkout[countryId], region);
});
} else {
return Spree.fillStates(Spree.Checkout[countryId], region);
}
}
};
fill_cities = function(country_code, cityId) {
$.ajax({
url: "/api/fetch_cities_from_aramex_address",
type: 'GET',
dataType: "json",
data: {
country_code: country_code
},
success: function(data) {
$(cityId).autocomplete({
source: data,
});
},
error: function() {}
});
}
Spree.fillStates = function(data, region) {
var selected, stateInput, statePara, stateSelect, stateSpanRequired, states, statesRequired, statesWithBlank;
statesRequired = data.states_required;
states = data.states;
statePara = $('#' + region + 'state');
stateSelect = statePara.find('select');
stateInput = statePara.find('input');
stateSpanRequired = statePara.find('[id$="state-required"]');
if (states.length > 0) {
selected = parseInt(stateSelect.val());
stateSelect.html('');
statesWithBlank = [{
name: '',
id: ''
}].concat(states);
$.each(statesWithBlank, function(idx, state) {
var opt;
opt = ($(document.createElement('option'))).attr('value', state.id).html(state.name);
if (selected === state.id) {
opt.prop('selected', true);
}
return stateSelect.append(opt);
});
stateSelect.prop('disabled', false).show();
stateInput.hide().prop('disabled', true);
statePara.show();
stateSpanRequired.show();
if (statesRequired) {
stateSelect.addClass('required');
}
stateSelect.removeClass('hidden');
return stateInput.removeClass('required');
} else {
stateSelect.hide().prop('disabled', true);
stateInput.show();
if (statesRequired) {
stateSpanRequired.show();
stateInput.addClass('required');
} else {
stateInput.val('');
stateSpanRequired.hide();
stateInput.removeClass('required');
}
statePara.toggle(!!statesRequired);
stateInput.prop('disabled', !statesRequired);
stateInput.removeClass('hidden');
return stateSelect.removeClass('required');
}
};
($('#bcountry select')).change(function() {
$('label.error').hide()
if (isCountryUsOrCa($("#order_bill_address_attributes_country_id").val())) {
$('#checkout_form_address').valid();
}
return Spree.updateState('b');
});
($('#scountry select')).change(function() {
$('label.error').hide()
if (isCountryUsOrCa($("#order_bill_address_attributes_country_id").val())) {
$('#checkout_form_address').valid();
}
return Spree.updateState('s');
});
Spree.updateState('b');
order_use_billing = $('input#order_use_billing');
order_use_billing.change(function() {
return update_shipping_form_state(order_use_billing);
});
update_shipping_form_state = function(order_use_billing) {
if (order_use_billing.is(':checked')) {
($('#shipping .inner')).hide();
return ($('#shipping .inner input, #shipping .inner select')).prop('disabled', true);
} else {
($('#shipping .inner')).show();
($('#shipping .inner input, #shipping .inner select')).prop('disabled', false);
return Spree.updateState('s');
}
};
return update_shipping_form_state(order_use_billing);
}
};
return Spree.onAddress();
});
为什么我会遇到顶部提到的问题?