Preface: this post is part of the Write Your First Trigger From Start to Finish series.
View Chapter 1 quiz questions without the answers!
Chapter 1 Questions:
1. If you can solve a business need using either a workflow or a trigger, which should you use?
2. Is it possible to write a trigger directly in a production Salesforce org?
3. What is Trigger.new and why is it so important?
4. Which version of the field name do you reference in triggers? Field Label or Field/API Name?
– Field Label: Favorite Color
– Field / API Name: Favorite_Color__c
5. Is it possible to deploy code to production without writing a test class?
6. How does your test class know which trigger to test?
7. True or false. Developers should avoid using comments as much as possible in code since comments are ignored by Salesforce.
8. At minimum, how many components must be added to a Change Set to deploy an Apex trigger?
Chapter 1 Practice Trigger:
Write a trigger that transfers every new contact to an Account named “Sfdc99”!
Don’t forget the test class!
Your answers should look something like this:
trigger TransferContact on Contact (before insert) { for (Contact contactInLoop : Trigger.new) { // This ID will be different in your org! contactInLoop.AccountId = '001i000000azqHs'; } }
@isTest public class TestTransferContact { static testMethod void insertNewContact() { Contact joe = new Contact(); joe.FirstName = 'Joe'; joe.LastName = 'Montana'; insert joe; } }
Too easy? Too hard? Post a comment and let me know!
Hi Pavan,
In the test class you need to create new Account as well along with new contact, Since we are querying the account using name condition. I also had similar kind of issues, code is working now , Hope this helps for you also :-)
Thanks for sharing…
From where we need to take this id ?
cont.AccountId = ‘001370000033eit’;
????
Hi Deepika,
Create and account with SFDC99, Then go to the account URL. In the URL between Account and view, you can get the ID.
Hi David,
Thanks for doing this!!!
My doubt is I have also used the contact.AccountId for the trigger that is mentioned above but my concern is where can i see this AccountId API Name.
Yes!! I know it’s an API Name. But for which one??
Account Name in Contact object or Account object.
If it is in contact object the API Name for Account Name is ‘Account’ right?
Please help me solve this. I’m bit confused :(
Account Name in Contact. Since it is a lookup field we are mentioning this as ‘AccountID’.
Thanks for sharing…
Iam facing the below error after apex test execution. Please help me fix this
System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, Transfer_Contact_to_Acc: execution of BeforeInsert
caused by: System.QueryException: List has no rows for assignment to SObject
Trigger.Transfer_Contact_to_Acc: line 5, column 1: []
Please reply
Hi Pavan,
In the test class you need to create new Account as well along with new contact, Since we are querying the account using name condition. I also had similar kind of issues, code is working now , Hope this helps for you also :-)
This is working fine.
Make sure all required fields are inserted and verify may be another trigger is restricting. Share the code if possible.
Hi David,
How do you figure out the API name for standard fields. e.g. How did you figure out the “accounted” field and put a condition on it.
Thanks
go to the standard object which contains the standard field that you are looking for (i.e. Setup –> Customize –> Opportunities –> Fields) then look for the exact standard field you wish to use in your code ( i.e. Stage) and Filed Name of Stage which is StageName is the API name.
Hello David,
Greetings!
Is it possible to view the created record(created in apex class) in contact object ?
trigger transferContact on Contact (before insert) {
Account a = new Account();
a.Description = ‘test’;
a.Name = ‘test’;
insert a;
for(Contact c : Trigger.New) {
c.Account = a;
}
}
What is wrong with this trigger ?
Account a = new Account();
Here you need to mention contact in place of account, as your trigger is for contact
in the for loop parse account id instead of name.
C.AccountId = a.Id;
Hi, David. Yes it is easy to follow your steps, but difficult to remember.
give me advice what easy way to remember when i need to used the record?
David,
Thanks for sharing your knowledge and your love of coding with the world :)
I was able to complete the quiz, but I’m still find my self just copying your syntax although I understand what the code should accomplish.
Just to let you know I’m mid-way through chapter 3 of Head First Java.
Head First Java will help with syntax =)
I talk about it a lot in the Apex Academy, but, you can learn without paying for the academy =) Only if you are lazier!
Hi David,
I’m just starting to code in salesforce for my org, and this site is helping me a lot. Thanks so much!
In this exercise I don’t understand this line of code (the most important one, omg!):
contactInLoop.AccountId = ‘001i000000azqHs’;
Could you help me understand it please?
Thnx!!!!
This line sets the AccountId of the contact to 001i000000azqHs =)
Not heard to comprehend, but I always struggle with wording and definitions. Kind of like I know how to speak english but don’t know the words. I’m a first time coder so i’m sure it will take me a while :-)
Hi David,
This is my trigger code
trigger transfercont on Contact (after insert) {
for (Contact cont : Trigger.new) {
cont.AccountId = ‘001370000033eit’;
update cont;
}
}
and my test class code is
@isTest
public class TestCont {
static TestMethod void Transfercont() {
Contact con1 = new Contact();
con1.LastName = ‘Vadambachery Murugesan’;
insert con1;
}
}
If i click on ‘Run Test’, my test class runs fine, but i don’t see a contact created with the last name that i specified in the test class.
So i tried to create a contact in contacts page manually, it threw me the below error
Error: Invalid Data.
Review all error messages below to correct your data.
Apex trigger transfercont caused an unexpected exception, contact your administrator: transfercont: execution of AfterInsert caused by: System.FinalException: Record is read-only: Trigger.transfercont: line 3, column 1
Please let me know what went wrong here. I recently signed up for a developer account and i’m the admin for the account.
Thanks,
Lakshman
Hi Lakshman,
Record insertion/updation using test class is temporary,they are rollbacked once the test class execution is finished.
Secondly, You’re firing the trigger after the record is inserted(event is after insert) and that is reason the AccountId field is read-only.
Change your trigger event to before insert.
From where we need to take this id ?
cont.AccountId = ‘001370000033eit’;
????
You’ll need to get it from an existing account. Either create a new account or refrences an existing account id from your org.
hi David when i try to make a TRIGGER i get an Error can you maybe help.
Thank you
trigger TransferContact on Contact (before insert) {
for (Contact contactInLoop : Trigger.new) {
// This ID will be different in your org!
contactInLoop.AccountId = ’00e24000000vTmo’;
}
}
ERROR:
Error Error: Compile Error: Incorrect SObject type: Contact should be Account at line 1 column 1
and when i change it to Account then this happens:
trigger TransferContact on Account (before insert) {
for (Account contactInLoop : Trigger.new) {
// This ID will be different in your org!
contactInLoop.AccountId = ’00e24000000vTmo’;
}
}
ERROR:
Error Error: Compile Error: Invalid field AccountId for SObject Account at line 4 column 5
ONE LAST QUESTION: do you recommend me to work with Sandbox because i am working on salesforce.com- Developer Edition.
thank you
Looks like you setup your trigger on the account sObject which is why your receiving error message 1 & 2 accountId would be just id on the account object the trigger you’re trying to write is meant to be on the contact sObject.
Developer-Edition should be fine. I just completed the quiz in that org with no issue.
How i do code coverage, I am using developer console when doing the test.
Also I want to test code above(transfer contact)and I can see the Account is hardcoded. So I want to test it with new Account that I created but it is not automatically creating an Account.
May be another question how will I test the Transfer Contact Trigger?
You will find answers to your questions as you keep reading through the chapters =)
I started today David and this comment marks the end my first trigger and test class (Chapter 1 + Quiz) =)
I found it to be pretty easy but I guess I shouldn’t get all ecstatic so soon. My gut feeling tells me that the tough is yet to come :P
I am new to salesforce and today only started your tutorial. I do have a salesforce developer edition account but cant find Sandbox. Is Sandbox not available for DE account…???If not, how can I deploy the test class I created in chapter 1.??
You’ll need a paid org with a sandbox if you want to deploy!
Hi Jagdish (and David),
I’m almost positive that you can try this by signing up for a 30-day training org for the Advanced Admin course. Org is still free but only lasts 30 days, but it has a sandbox you can use.
https://www.salesforce.com/form/signup/freetrial_training.jsp#submit
You want the Administration Essentials for Experienced Admin course.
At least this way you get to see it deploy
Great tip Geoff!!!
Hi David,
I just love the way you have laid out these tutorials and quizzes. Being an admin, I know how formidable it feels to approach Salesforce’s dev side.But you have made it very less so. Thanks a lot buddy.
Below is my attempt at the practice trigger
Trigger
trigger TransferContact on Contact (before insert) {
Account accountObj = [Select Id from Account where Name = ‘Contact Holder’ limit 1];
Contact[] contacts = Trigger.new;
for(Contact c: contacts){
c.AccountID = accountObj.Id;
}
}
Test class
@isTest
public class TestTransferContact {
static testMethod void createContact(){
Account a = new Account();
a.Name = ‘Contact Holder’;
insert a;
Account insertedAccount = [Select Id from Account where Name = ‘Contact Holder’];
Contact c = new Contact();
c.LastName = ‘Doe’;
insert c;
Contact insertedContact = [Select Id, AccountId from Contact where id =:c.id];
System.assertEquals(insertedAccount.id, insertedContact.AccountId, ‘Success’);
}
}
Hoping you like it :)
This is an excellent trigger/test class =)
There’s nothing significant that I’d change about it – be very proud of yourself!!!!
The most important part of what you’ve written is that I can tell you fundamentally understand why you’re doing certain things. That’s the most important part of learning!
is this right to write
System.assertEquals(a.id,c.id, ‘Success’);
Only two arguments in System.assertEquals!
instead of writing “Account insertedAccount = [Select Id from Account where Name = ‘Contact Holder’]; why cant we use just a.id
and also why cant we use c.accountId instead of “Contact insertedContact = [Select Id, AccountId from Contact where id =:c.id];”
for the sake of System.assertEquals().
sorry if iam not clear
Hi David,
I see people using “SELECT Id from Account WHERE Name ” verbiage. Where can I find explanation and learn how to implement this text. I know its SQL, but it there a place to learn and understand this through Salesforce?..Still learning.
BTW, passed my developer exam in September.
Chapter 2 right here buddy!
https://www.sfdc99.com/beginner-tutorials/
CONGRATS on DEV 401! Did you study with the guides here?
David
Yes, but bounced around a bit on the internet using different study guides.. Fundamentals workbook is a must. I went through it 3 times. Will try to battle ADM 201 next, but concentrating on coding.. Also trying to get a non-profit Salesforce job, but experience is deterring my success, but will keep trying. On to Chapter 2… Thanks for all your help.
I was trying to combine this with system.assertEquals and got stuck. I switched to System.debug to try and figure it out, but I’m hoping for some clarification on the relationship between the test class and what the trigger is doing. I wanted the test class to verify that the trigger was working as expected, but it seems that I have to set the AccountId on the Contact record in the test class as well. I don’t quite understand why
Trigger:
trigger TransferContacts on Contact (before insert) {
for (Contact c : trigger.new){
//Get the Account Sfdc99’s Id
Account a = [SELECT Id from Account WHERE Name = ‘Sfdc99’ LIMIT 1];
c.AccountId = a.Id;
}
}
Test Class:
@isTest
public class TestTransferContacts {
static testMethod void TestTransfers(){
//Create records from scratch
Account a = new Account();
a.Name = ‘Sfdc99’;
insert a;
Contact c = new Contact();
c.Lastname = ‘Kelso’;
//c.AccountId = a.Id; //Why do I have to declare this? Shouldn’t the trigger do it?
insert c;
System.debug(c.AccountId); //Shows as null when I comment out declaring c.AccountId=a.Id
}
}
ok, I got system.assertEquals to work by requerying the Contact. Can you just explain why I need to requery updated results?
System.assertEquals(‘Sfdc99’, [SELECT Account.Name FROM Contact WHERE Id = :c.Id].Account.Name);
Your variables won’t automatically update to their latest values if you don’t re query. The only exception is ID I believe. =)
Thanks! Is calling the new values right in the assert considered the right way to do it or is there a better way to say something to the effect of “update variable values” prior to system.assertequals?
The more common way is to do the query first, save the results in a variable, then use that variable in your assert. Having it all on one line certainly works but it’s just a little less readable =)
For beginners your site is superb…
Hi David,
I discovered your site a little late. I have gone through your webinars and your quizlets. It’s a great site, thanks for building such a nice site.
Thank you!
david your codes are so intresting and easy to understand
David,
I’m going over the tutorials again. question, is it safe to say to have an order of procedures you follow when creating a trigger. for example, you make sure you know all the required fields in a record, their API names, etc. do you have a layout of everything you look at before you start coding?
Yes that is fair!
But usually I find out the hard way when testing instead =) Either way you’re going to find out!
Hi David, I wrote the trigger on contacts in a different way, but thats not giving me a 75% coverage… In such situation how shall i write my test class.
My trigger:
trigger AssocConToAccount on Contact (before insert) {
list con = new list();
account accId = [select id from account limit 1];
id i = accId.id;
for(contact c : Trigger.new)
{
c.AccountId = i;
con.add(c);
}
insert con;
Test class is same as yours….but its not giving me full coverage.. What do you think,where I need to check.
Create a test class does does all the following:
1. Creates an Account
2. Creates a Contact
If you don’t do step 1 you’ll get an error when you do the SOQL query on Accounts!
Hi David,
Thanks for your help. Just want to ask difference b/w before and After? What if we use after insert?
Check out this post!
https://www.sfdc99.com/2014/01/25/use-vs-triggers/
I have tried multiple ways to learn to code Apex. I have learned some things but not really a great understanding of Apex. Just going through Chapter 1 has made things I’ve been trying to understand for the past year so easy and clear. The thing that has stood out the most is the Test Class and how to write a Test Class. I feel so confident right now about writing simple Triggers and Test Classes. You have made things so easy, fun, and clear for me to understand.
Awww, thank you Ronnie!
its Awesome!!!!
Fun to learn, neat, clear & simple.
loving to code now :)
Thanks David
Glad you’re having a good time – that’s the most important part!!
Hello David! you are doing a great job for beginners like me. i am facing an error while saving that code “Error: Compile Error: Incorrect SObject type: Contact should be User at line 1 column 1”.i”ll be grateful to you if you can tell me where am i doing mistake.Thanks
Post your code and I’ll take a look!
trigger TransferContact on Contact (before insert) {
for (Contact contactInLoop : Trigger.new) {
// This ID will be different in your org!
contactInLoop.AccountId = ‘001900000102Ihq’;
}
}
i am facing an error while saving that code “Error: Compile Error: Incorrect SObject type: Contact should be User at line 1 column 1″.i”ll be grateful to you if you can tell me where am i doing mistake.Thanks
Make sure to do it from the Contact tab!
Really helpful thank you David :0
David,
You have created an Account called SFDC99 and you are using the RecordID of the account SFDC99 right?
Correct!
Its a great tutorial for beginners !!
Hi David,
Please can you tell me how the last line of your trigger
“contactInLoop.AccountId = ‘001i000000azqHs’;” worked. Means how did it tranfers the contacts to this Account
Thanks
AccountId is a standard field (lookup) on every Contact that points to the Account it lives under =)
Lookup fields are always set by IDs of the records, so in this case we are setting it to the ID of a specific Account!
Thanks David, This is really fun! :)
Sweet!!!
Hi, David. Why did you make your test class public? Could it have been private? Thanks!
It definitely could have been private!
http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_testing_unit_tests.htm
You can choose either with very few ramifications =) I chose public because it raises less questions LOL
How to debug this Trigger?
Check out this post Mini!
https://www.sfdc99.com/2014/02/22/debug-your-code-with-system-debug/
David I want more examples about how to write triggers
Hi David,
a couple of months ago I stumbled upon your name and your skills while reading an article about the Salesforce Hackaton and your participation there. I was really amazed that you have reached all your expert skills by teeching you this only by yourself !!! My deepest respect and appreciation to you !
I think lots of people are afraid of starting coding because they fear the vast amount of knowledge needed to be a good Salesforce Developer. Thank you SO MUCH giving us confidence that everyone can learn to code !!! This is what every beginner needs the most !
I just finished the Chapter 1 excerces and the Quizes section – all the explanations and code samples you provided here were prepared really great from the didactic point of view and were really easy to understand ! Thank you so much for doing this !
Before continuing to Chapter 2 I’d love to practice even more the creation of Triggers and strenghten my newly achieved skills. Can you provide us with some more of these excellent easy-to-use Trigger exercises ? Thx !
Greetings
Simeon
Here’s one for you Simeon: write a trigger that creates a new Opportunity whenever an Account is created!
Honored to have a fan! =)
David
This website makes learning Apex so much easier than any of the books that I have been trying to read! This trigger that you recommended Simeon create as another quiz, would it be possible to get the solution posted? I appreciate your help!
Oops. I put my email in the name space and name in the email space. Would it be possible to either delete or fix my previous comment?
Done! I owe you a quiz answer too!
Hi David … Wat is the ans for the above trigger
David, thank you so much for doing this. I have been struggling for weeks and, for whatever reason, none of it made sense until now. Your explanations are very detailed and thorough and make the process of learning this platform so much easier.
Hi David, thank you for your willingness to help others,
Are there any plans to explain and teach on the standard syntax stuff? For example:
Public class
Static
Void
Etc
Yup! We’ll actually cover some of that stuff in the next chapter!
There’s a book that teaches this 100000X better than I can – this book changed my life and I highly recommend it!
https://www.sfdc99.com/2013/05/20/the-best-way-to-quickly-learn-how-to-code-in-salesforce/
Worth the $25 or so dollars, promise!
David
Easy start is motivating..innit!
You can do it Simi!!!!
Great effort!
Very useful for beginners.
Waiting to see more from you!
Thank you Anu =)
Nice one !
Can use Account acc =[Select id from Account where Name=’Sfdc99′ limit 1];
Id accId = acc.id;
and assign it as contactInLoop.AccountId =accId;
We need more quizzes and level upgraded.
Thanks
You sure can! That way is much better than mine actually, hahaha!
(Btw did you mean I should make these quizzes more difficult? Happy to do so!)
Love to see if quizzes are divided into level by.
Privileged to see your reply.
Thank you very much.
I’ll do a quiz for each chapter – so they’ll get progressively more difficult!
Mr David I want more examples about triggers
Write a trigger that creates a Case for every new Account!