Cannot move query outside of FOR loop?
REQUIREMENT: Need to move the query outside of the FOR loop in Opportunity trigger.
PROBLEM: After moving query outside of the FOR loop, I receive an error when trying to save a new Opportunity record (when it is triggered).
Original Code (no issues):
trigger myTrigger on Opportunity (before insert) {
Set<Id> parentAccountIds = new Set<Id>();
for(Opportunity opp : Trigger.new) {
parentAccountIds.add(opp.AccountId);
//query fields on parent accounts and map them by Account Id
Map<Id, Account> parentAccountsById = new Map<Id, Account>([
select Id, CustomField__c
from Account
where Id in :parentAccountIds
]);
if(String.isNotBlank(opp.AccountId)) {
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
// do stuff
}
}
}
Code after moving the query, has error (see below):
trigger myTrigger on Opportunity (before insert) {
Set<Id> parentAccountIds = new Set<Id>();
//query fields on parent accounts and map them by Account Id
Map<Id, Account> parentAccountsById = new Map<Id, Account>([
select Id, CustomField__c
from Account
where Id in :parentAccountIds
]);
for(Opportunity opp : Trigger.new) {
parentAccountIds.add(opp.AccountId);
if(String.isNotBlank(opp.AccountId)) {
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
// do stuff
}
}
}
ERROR:
myTrigger: execution of BeforeInsert caused by:
System.NullPointerException: Attempt to de-reference a null object
Trigger.myTrigger: line 22, column 1
LINE 22 refers TO:
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
apex trigger soql class for
add a comment |
REQUIREMENT: Need to move the query outside of the FOR loop in Opportunity trigger.
PROBLEM: After moving query outside of the FOR loop, I receive an error when trying to save a new Opportunity record (when it is triggered).
Original Code (no issues):
trigger myTrigger on Opportunity (before insert) {
Set<Id> parentAccountIds = new Set<Id>();
for(Opportunity opp : Trigger.new) {
parentAccountIds.add(opp.AccountId);
//query fields on parent accounts and map them by Account Id
Map<Id, Account> parentAccountsById = new Map<Id, Account>([
select Id, CustomField__c
from Account
where Id in :parentAccountIds
]);
if(String.isNotBlank(opp.AccountId)) {
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
// do stuff
}
}
}
Code after moving the query, has error (see below):
trigger myTrigger on Opportunity (before insert) {
Set<Id> parentAccountIds = new Set<Id>();
//query fields on parent accounts and map them by Account Id
Map<Id, Account> parentAccountsById = new Map<Id, Account>([
select Id, CustomField__c
from Account
where Id in :parentAccountIds
]);
for(Opportunity opp : Trigger.new) {
parentAccountIds.add(opp.AccountId);
if(String.isNotBlank(opp.AccountId)) {
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
// do stuff
}
}
}
ERROR:
myTrigger: execution of BeforeInsert caused by:
System.NullPointerException: Attempt to de-reference a null object
Trigger.myTrigger: line 22, column 1
LINE 22 refers TO:
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
apex trigger soql class for
add a comment |
REQUIREMENT: Need to move the query outside of the FOR loop in Opportunity trigger.
PROBLEM: After moving query outside of the FOR loop, I receive an error when trying to save a new Opportunity record (when it is triggered).
Original Code (no issues):
trigger myTrigger on Opportunity (before insert) {
Set<Id> parentAccountIds = new Set<Id>();
for(Opportunity opp : Trigger.new) {
parentAccountIds.add(opp.AccountId);
//query fields on parent accounts and map them by Account Id
Map<Id, Account> parentAccountsById = new Map<Id, Account>([
select Id, CustomField__c
from Account
where Id in :parentAccountIds
]);
if(String.isNotBlank(opp.AccountId)) {
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
// do stuff
}
}
}
Code after moving the query, has error (see below):
trigger myTrigger on Opportunity (before insert) {
Set<Id> parentAccountIds = new Set<Id>();
//query fields on parent accounts and map them by Account Id
Map<Id, Account> parentAccountsById = new Map<Id, Account>([
select Id, CustomField__c
from Account
where Id in :parentAccountIds
]);
for(Opportunity opp : Trigger.new) {
parentAccountIds.add(opp.AccountId);
if(String.isNotBlank(opp.AccountId)) {
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
// do stuff
}
}
}
ERROR:
myTrigger: execution of BeforeInsert caused by:
System.NullPointerException: Attempt to de-reference a null object
Trigger.myTrigger: line 22, column 1
LINE 22 refers TO:
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
apex trigger soql class for
REQUIREMENT: Need to move the query outside of the FOR loop in Opportunity trigger.
PROBLEM: After moving query outside of the FOR loop, I receive an error when trying to save a new Opportunity record (when it is triggered).
Original Code (no issues):
trigger myTrigger on Opportunity (before insert) {
Set<Id> parentAccountIds = new Set<Id>();
for(Opportunity opp : Trigger.new) {
parentAccountIds.add(opp.AccountId);
//query fields on parent accounts and map them by Account Id
Map<Id, Account> parentAccountsById = new Map<Id, Account>([
select Id, CustomField__c
from Account
where Id in :parentAccountIds
]);
if(String.isNotBlank(opp.AccountId)) {
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
// do stuff
}
}
}
Code after moving the query, has error (see below):
trigger myTrigger on Opportunity (before insert) {
Set<Id> parentAccountIds = new Set<Id>();
//query fields on parent accounts and map them by Account Id
Map<Id, Account> parentAccountsById = new Map<Id, Account>([
select Id, CustomField__c
from Account
where Id in :parentAccountIds
]);
for(Opportunity opp : Trigger.new) {
parentAccountIds.add(opp.AccountId);
if(String.isNotBlank(opp.AccountId)) {
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
// do stuff
}
}
}
ERROR:
myTrigger: execution of BeforeInsert caused by:
System.NullPointerException: Attempt to de-reference a null object
Trigger.myTrigger: line 22, column 1
LINE 22 refers TO:
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
apex trigger soql class for
apex trigger soql class for
edited Nov 16 '18 at 23:09
Sebastian Kessel
8,75552136
8,75552136
asked Nov 16 '18 at 22:24
paulK
637
637
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
The answer by the OP does solve the problem, but I'd like to go into more detail about why it works (and why the initial attempt didn't work).
Let's take the bottom-most loop over Trigger.new
for(Opportunity opp : Trigger.new) {
if(String.isNotBlank(opp.AccountId)) {
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
// do stuff
}
}
The if
statement ensures that our Opportunity
does indeed have an AccountId
, but we can still run into a Null Pointer Exception (NPE).
Without performing some sort of null check on the map (or result), parentAccountsById.get(opp.AccountId)
can return null
.
null.<anything>
results in an NPE, because null
has no properties, variables, or methods.
Looking at OP's full first attempt (with my own comments):
trigger myTrigger on Opportunity (before insert) {
// This line both declares and initializes parentAccountIds
// This allows us to use the standard set methods, but the set is empty
Set<Id> parentAccountIds = new Set<Id>();
// In this query, we haven't put anything into parentAccountIds
// This query will thus return 0 rows, but still give us our initialization
// for the map parentAccountsById.
// We can call any standard method of the Map class, but the map will contain nothing
Map<Id, Account> parentAccountsById = new Map<Id, Account>([
select Id, CustomField__c
from Account
where Id in :parentAccountIds
]);
for(Opportunity opp : Trigger.new) {
// We're adding accountIds to the parentAccountIds set _after_ running
// the query
parentAccountIds.add(opp.AccountId);
if(String.isNotBlank(opp.AccountId)) {
// The opp's AccountId is not blank, but because we have nothing in
// parentAccountsById, we end up trying to call null.CustomField__c
// which results in an NPE
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
// do stuff
}
}
}
The solution, as illustrated by paulK, is to use the following pattern:
- Declare/initialize a collection
- Iterate over
Trigger.new
, and add the Ids to the collection - Perform a query, using the collection of Ids gathered previously
- Iterate over
Trigger.new
again, this time doing the work you want to actually do
Again, the key part of this pattern is that we iterate twice over Trigger.new
. We need to gather the Ids we want to use in the query before we execute the query.
Nice explanation, Derek! Have an upvote!
– paulK
Nov 16 '18 at 23:25
add a comment |
Ok, found the solution...
trigger myTrigger on Opportunity (before insert) {
Set<Id> parentAccountIds = new Set<Id>();
for(Opportunity newOpp : Trigger.new) {
parentAccountIds.add(newOpp.AccountId);
}
//query fields on parent accounts and map them by Account Id
Map<Id, Account> parentAccountsById = new Map<Id, Account>([
select Id, CustomField__c
from Account
where Id in :parentAccountIds
]);
for(Opportunity opp : Trigger.new) {
if(String.isNotBlank(opp.AccountId)) {
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
// do stuff
}
}
}
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "459"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f239684%2fcannot-move-query-outside-of-for-loop%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
The answer by the OP does solve the problem, but I'd like to go into more detail about why it works (and why the initial attempt didn't work).
Let's take the bottom-most loop over Trigger.new
for(Opportunity opp : Trigger.new) {
if(String.isNotBlank(opp.AccountId)) {
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
// do stuff
}
}
The if
statement ensures that our Opportunity
does indeed have an AccountId
, but we can still run into a Null Pointer Exception (NPE).
Without performing some sort of null check on the map (or result), parentAccountsById.get(opp.AccountId)
can return null
.
null.<anything>
results in an NPE, because null
has no properties, variables, or methods.
Looking at OP's full first attempt (with my own comments):
trigger myTrigger on Opportunity (before insert) {
// This line both declares and initializes parentAccountIds
// This allows us to use the standard set methods, but the set is empty
Set<Id> parentAccountIds = new Set<Id>();
// In this query, we haven't put anything into parentAccountIds
// This query will thus return 0 rows, but still give us our initialization
// for the map parentAccountsById.
// We can call any standard method of the Map class, but the map will contain nothing
Map<Id, Account> parentAccountsById = new Map<Id, Account>([
select Id, CustomField__c
from Account
where Id in :parentAccountIds
]);
for(Opportunity opp : Trigger.new) {
// We're adding accountIds to the parentAccountIds set _after_ running
// the query
parentAccountIds.add(opp.AccountId);
if(String.isNotBlank(opp.AccountId)) {
// The opp's AccountId is not blank, but because we have nothing in
// parentAccountsById, we end up trying to call null.CustomField__c
// which results in an NPE
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
// do stuff
}
}
}
The solution, as illustrated by paulK, is to use the following pattern:
- Declare/initialize a collection
- Iterate over
Trigger.new
, and add the Ids to the collection - Perform a query, using the collection of Ids gathered previously
- Iterate over
Trigger.new
again, this time doing the work you want to actually do
Again, the key part of this pattern is that we iterate twice over Trigger.new
. We need to gather the Ids we want to use in the query before we execute the query.
Nice explanation, Derek! Have an upvote!
– paulK
Nov 16 '18 at 23:25
add a comment |
The answer by the OP does solve the problem, but I'd like to go into more detail about why it works (and why the initial attempt didn't work).
Let's take the bottom-most loop over Trigger.new
for(Opportunity opp : Trigger.new) {
if(String.isNotBlank(opp.AccountId)) {
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
// do stuff
}
}
The if
statement ensures that our Opportunity
does indeed have an AccountId
, but we can still run into a Null Pointer Exception (NPE).
Without performing some sort of null check on the map (or result), parentAccountsById.get(opp.AccountId)
can return null
.
null.<anything>
results in an NPE, because null
has no properties, variables, or methods.
Looking at OP's full first attempt (with my own comments):
trigger myTrigger on Opportunity (before insert) {
// This line both declares and initializes parentAccountIds
// This allows us to use the standard set methods, but the set is empty
Set<Id> parentAccountIds = new Set<Id>();
// In this query, we haven't put anything into parentAccountIds
// This query will thus return 0 rows, but still give us our initialization
// for the map parentAccountsById.
// We can call any standard method of the Map class, but the map will contain nothing
Map<Id, Account> parentAccountsById = new Map<Id, Account>([
select Id, CustomField__c
from Account
where Id in :parentAccountIds
]);
for(Opportunity opp : Trigger.new) {
// We're adding accountIds to the parentAccountIds set _after_ running
// the query
parentAccountIds.add(opp.AccountId);
if(String.isNotBlank(opp.AccountId)) {
// The opp's AccountId is not blank, but because we have nothing in
// parentAccountsById, we end up trying to call null.CustomField__c
// which results in an NPE
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
// do stuff
}
}
}
The solution, as illustrated by paulK, is to use the following pattern:
- Declare/initialize a collection
- Iterate over
Trigger.new
, and add the Ids to the collection - Perform a query, using the collection of Ids gathered previously
- Iterate over
Trigger.new
again, this time doing the work you want to actually do
Again, the key part of this pattern is that we iterate twice over Trigger.new
. We need to gather the Ids we want to use in the query before we execute the query.
Nice explanation, Derek! Have an upvote!
– paulK
Nov 16 '18 at 23:25
add a comment |
The answer by the OP does solve the problem, but I'd like to go into more detail about why it works (and why the initial attempt didn't work).
Let's take the bottom-most loop over Trigger.new
for(Opportunity opp : Trigger.new) {
if(String.isNotBlank(opp.AccountId)) {
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
// do stuff
}
}
The if
statement ensures that our Opportunity
does indeed have an AccountId
, but we can still run into a Null Pointer Exception (NPE).
Without performing some sort of null check on the map (or result), parentAccountsById.get(opp.AccountId)
can return null
.
null.<anything>
results in an NPE, because null
has no properties, variables, or methods.
Looking at OP's full first attempt (with my own comments):
trigger myTrigger on Opportunity (before insert) {
// This line both declares and initializes parentAccountIds
// This allows us to use the standard set methods, but the set is empty
Set<Id> parentAccountIds = new Set<Id>();
// In this query, we haven't put anything into parentAccountIds
// This query will thus return 0 rows, but still give us our initialization
// for the map parentAccountsById.
// We can call any standard method of the Map class, but the map will contain nothing
Map<Id, Account> parentAccountsById = new Map<Id, Account>([
select Id, CustomField__c
from Account
where Id in :parentAccountIds
]);
for(Opportunity opp : Trigger.new) {
// We're adding accountIds to the parentAccountIds set _after_ running
// the query
parentAccountIds.add(opp.AccountId);
if(String.isNotBlank(opp.AccountId)) {
// The opp's AccountId is not blank, but because we have nothing in
// parentAccountsById, we end up trying to call null.CustomField__c
// which results in an NPE
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
// do stuff
}
}
}
The solution, as illustrated by paulK, is to use the following pattern:
- Declare/initialize a collection
- Iterate over
Trigger.new
, and add the Ids to the collection - Perform a query, using the collection of Ids gathered previously
- Iterate over
Trigger.new
again, this time doing the work you want to actually do
Again, the key part of this pattern is that we iterate twice over Trigger.new
. We need to gather the Ids we want to use in the query before we execute the query.
The answer by the OP does solve the problem, but I'd like to go into more detail about why it works (and why the initial attempt didn't work).
Let's take the bottom-most loop over Trigger.new
for(Opportunity opp : Trigger.new) {
if(String.isNotBlank(opp.AccountId)) {
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
// do stuff
}
}
The if
statement ensures that our Opportunity
does indeed have an AccountId
, but we can still run into a Null Pointer Exception (NPE).
Without performing some sort of null check on the map (or result), parentAccountsById.get(opp.AccountId)
can return null
.
null.<anything>
results in an NPE, because null
has no properties, variables, or methods.
Looking at OP's full first attempt (with my own comments):
trigger myTrigger on Opportunity (before insert) {
// This line both declares and initializes parentAccountIds
// This allows us to use the standard set methods, but the set is empty
Set<Id> parentAccountIds = new Set<Id>();
// In this query, we haven't put anything into parentAccountIds
// This query will thus return 0 rows, but still give us our initialization
// for the map parentAccountsById.
// We can call any standard method of the Map class, but the map will contain nothing
Map<Id, Account> parentAccountsById = new Map<Id, Account>([
select Id, CustomField__c
from Account
where Id in :parentAccountIds
]);
for(Opportunity opp : Trigger.new) {
// We're adding accountIds to the parentAccountIds set _after_ running
// the query
parentAccountIds.add(opp.AccountId);
if(String.isNotBlank(opp.AccountId)) {
// The opp's AccountId is not blank, but because we have nothing in
// parentAccountsById, we end up trying to call null.CustomField__c
// which results in an NPE
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
// do stuff
}
}
}
The solution, as illustrated by paulK, is to use the following pattern:
- Declare/initialize a collection
- Iterate over
Trigger.new
, and add the Ids to the collection - Perform a query, using the collection of Ids gathered previously
- Iterate over
Trigger.new
again, this time doing the work you want to actually do
Again, the key part of this pattern is that we iterate twice over Trigger.new
. We need to gather the Ids we want to use in the query before we execute the query.
answered Nov 16 '18 at 23:00
Derek F
19k31849
19k31849
Nice explanation, Derek! Have an upvote!
– paulK
Nov 16 '18 at 23:25
add a comment |
Nice explanation, Derek! Have an upvote!
– paulK
Nov 16 '18 at 23:25
Nice explanation, Derek! Have an upvote!
– paulK
Nov 16 '18 at 23:25
Nice explanation, Derek! Have an upvote!
– paulK
Nov 16 '18 at 23:25
add a comment |
Ok, found the solution...
trigger myTrigger on Opportunity (before insert) {
Set<Id> parentAccountIds = new Set<Id>();
for(Opportunity newOpp : Trigger.new) {
parentAccountIds.add(newOpp.AccountId);
}
//query fields on parent accounts and map them by Account Id
Map<Id, Account> parentAccountsById = new Map<Id, Account>([
select Id, CustomField__c
from Account
where Id in :parentAccountIds
]);
for(Opportunity opp : Trigger.new) {
if(String.isNotBlank(opp.AccountId)) {
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
// do stuff
}
}
}
add a comment |
Ok, found the solution...
trigger myTrigger on Opportunity (before insert) {
Set<Id> parentAccountIds = new Set<Id>();
for(Opportunity newOpp : Trigger.new) {
parentAccountIds.add(newOpp.AccountId);
}
//query fields on parent accounts and map them by Account Id
Map<Id, Account> parentAccountsById = new Map<Id, Account>([
select Id, CustomField__c
from Account
where Id in :parentAccountIds
]);
for(Opportunity opp : Trigger.new) {
if(String.isNotBlank(opp.AccountId)) {
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
// do stuff
}
}
}
add a comment |
Ok, found the solution...
trigger myTrigger on Opportunity (before insert) {
Set<Id> parentAccountIds = new Set<Id>();
for(Opportunity newOpp : Trigger.new) {
parentAccountIds.add(newOpp.AccountId);
}
//query fields on parent accounts and map them by Account Id
Map<Id, Account> parentAccountsById = new Map<Id, Account>([
select Id, CustomField__c
from Account
where Id in :parentAccountIds
]);
for(Opportunity opp : Trigger.new) {
if(String.isNotBlank(opp.AccountId)) {
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
// do stuff
}
}
}
Ok, found the solution...
trigger myTrigger on Opportunity (before insert) {
Set<Id> parentAccountIds = new Set<Id>();
for(Opportunity newOpp : Trigger.new) {
parentAccountIds.add(newOpp.AccountId);
}
//query fields on parent accounts and map them by Account Id
Map<Id, Account> parentAccountsById = new Map<Id, Account>([
select Id, CustomField__c
from Account
where Id in :parentAccountIds
]);
for(Opportunity opp : Trigger.new) {
if(String.isNotBlank(opp.AccountId)) {
Date CustomField = parentAccountsById.get(opp.AccountId).CustomField__c;
// do stuff
}
}
}
answered Nov 16 '18 at 22:29
paulK
637
637
add a comment |
add a comment |
Thanks for contributing an answer to Salesforce Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f239684%2fcannot-move-query-outside-of-for-loop%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown