Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon

Building a Private App

Save for later
  • 14 min read
  • 23 May 2014

article-image

(For more resources related to this topic, see here.)

Even though the app will be simple and only take a few hours to build, we'll still use good development practices to ensure we create a solid foundation. There are many different approaches to software development and discussing even a fraction of them is beyond the scope of this book. Instead, we'll use a few common concepts, such as requirements gathering, milestones, Test-Driven Development (TDD), frequent code check-ins, and appropriate commenting/documentation. Personal discipline in following development procedures is one of the best things a developer can bring to a project; it is even more important than writing code.

This article will cover the following topics:

  • The structure of the app we'll be building

  • The development process

  • Working with the Shopify API

  • Using source control

  • Deploying to production

Signing up for Shopify

Before we dive back into code, it would be helpful to get the task of setting up a Shopify store out of the way. Sign up as a Shopify partner by going to http://partners.shopify.com. The benefit of this is that partners can provision stores that can be used for testing. Go ahead and make one now before reading further. Keep your login information close at hand; we'll need it in just a moment.

Understanding our workflow

The general workflow for developing our application is as follows:

  1. Pull down the latest version of the master branch.

  2. Pick a feature to implement from our requirements list.

  3. Create a topic branch to keep our changes isolated.

  4. Write tests that describe the behavior desired by our feature.

  5. Develop the code until it passes all the tests.

  6. Commit and push the code into the remote repository.

  7. Pull down the latest version of the master branch and merge it with our topic branch.

  8. Run the test suite to ensure that everything still works.

  9. Merge the code back with the master branch.

  10. Commit and push the code to the remote repository.

The previous list should give you a rough idea of what is involved in a typical software project involving multiple developers. The use of topic branches ensures that our work in progress won't affect other developers (called breaking the build) until we've confirmed that our code has passed all the tests and resolved any conflicts by merging in the latest stable code from the master branch.

The practical upside of this methodology is that it allows bug fixes or work from another developer to be added to the project at any time without us having to worry about incomplete code polluting the build. This also gives us the ability to deploy production from a stable code base.

In practice, a lot of projects will also have a production branch (or tagged release) that contains a copy of the code currently running in production. This is primarily in case of a server failure so that the application can be restored without having to worry about new features being released ahead of schedule, and secondly so that if a new deploy introduces bugs, it can easily be rolled back.

Building the application

We'll be building an application that allows Shopify storeowners to organize contests for their shoppers and randomly select a winner. Contests can be configured based on purchase history and timeframe. For example, a contest could be organized for all the customers who bought the newest widget within the last three days, or anyone who has made an order for any product in the month of August. To accomplish this, we'll need to be able to pull down order information from the Shopify store, generate a random winner, and show the storeowner the results.

Let's start out by creating a list of requirements for our application. We'll use this list to break our development into discrete pieces so we can easily measure our progress and also keep our focus on the important features. Of course, it's difficult to make a complete list of all the requirements and have it stick throughout the development process, which is why a common strategy is to develop in iterations (or sprints). The result of an iteration is a working app that can be reviewed by the client so that the remaining features can be reprioritized if necessary.

High-level requirements

The requirements list comprises all the tasks we're going to accomplish in this article. The end result will be an application that we can use to run a contest for a single Shopify store. Included in the following list are any related database, business logic, and user interface coding necessary.

  1. Install a few necessary gems.

  2. Store Shopify API credentials.

  3. Connect to Shopify.

  4. Retrieve order information from Shopify.

  5. Retrieve product information from Shopify.

  6. Clean up the UI.

  7. Pick a winner from a list.

  8. Create contests.

Now that we have a list of requirements, we can treat each one as a sprint. We will work in a topic branch and merge our code to the master branch at the end of the sprint.

Installing a few necessary gems

The first item on our list is to add a few code libraries (gems) to our application. Let's create a topic branch and do just that. To avoid confusion over which branch contains code for which feature, we can start the branch name with the requirement number. We'll additionally prepend the chapter number for clarity, so our format will be <chapter #>_<requirement #>_<branch name>. Execute the following command line in the root folder of the app:

git checkout -b ch03_01_gem_updates

This command will create a local branch called ch03_01_gem_updates that we will use to isolate our code for this feature. Once we've installed all the gems and verified that the application runs correctly, we'll merge our code back with the master branch.

At a minimum we need to install the gems we want to use for testing. For this app we'll use RSpec. We'll need to use the development and test group to make sure the testing gems aren't loaded in production.

  1. Add the following code in bold to the block present in the Gemfile:

    group :development, :test do gem "sqlite3" # Helpful gems gem "better_errors" # improves error handling gem "binding_of_caller" # used by better errors # Testing frameworks gem 'rspec-rails' # testing framework gem "factory_girl_rails" # use factories, not fixtures gem "capybara" # simulate browser activity gem "fakeweb" # Automated testing gem 'guard' # automated execution of test suite upon change gem "guard-rspec" # guard integration with rspec # Only install the rb-fsevent gem if on Max OSX gem 'rb-fsevent' # used for Growl notifications end

  2. Now we need to head over to the terminal and install the gems via Bundler with the following command:

    bundle install

  3. The next step is to install RSpec:

    rails generate rspec:install

  4. The final step is to initialize Guard:

    guard init rspec

    This will create a Guard file, and fill it with the default code needed to detect the file changes.

  5. We can now restart our Rails server and verify that everything works properly. We have to do a full restart to ensure that any initialization files are properly picked up. Once we've ensured that our page loads without issue, we can commit our code and merge it back with the master branch:

    git add --all git commit -am "Added gems for testing" git checkout master git merge ch03_01_gem_updates git push

Great! We've completed our first requirement.

Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime

Storing Shopify API credentials

In order to access our test store's API, we'll need to create a Private App and store the provided credentials there for future use. Fortunately, Shopify makes this easy for us via the Admin UI:

  1. Go to the Apps page.

  2. At the bottom of the page, click on the Create a private API key… link.

  3. Click on the Generate new Private App button.

    We'll now be provided with three important pieces of information: the API Key, password, and shared secret. In addition, we can see from the example URL field that we need to track our Shopify URL as well.

  4. Now that we have credentials to programmatically access our Shopify store, we can save this in our application. Let's create a topic branch and get to work:

    git checkout -b ch03_02_shopify_credentials

  5. Rails offers a generator called a scaffold that will create the database migration model, controller, view files, and test stubs for us. Run the following from the command line to create the scaffold for the Account vertical (make sure it is all on one line):

    rails g scaffold Account shopify_account_url:string shopify_
    api_key:string shopify_password:string shopify_shared
    _secret:string

  6. We'll need to run the database migration to create the database table using the following commands:

    bundle exec rake db:migrate bundle exec rake db:migrate RAILS_ENV=test

  7. Use the following command to update the generated view files to make them bootstrap compatible:

    rails g bootstrap:themed Accounts -f

  8. Head over to http://localhost:3000/accounts and create a new account in our app that uses the Shopify information from the Private App page.

  9. It's worth getting Guard to run our test suite every time we make a change so we can ensure that we don't break anything. Open up a new terminal in the root folder of the app and start up Guard:

    bundle exec guard

After booting up, Guard will automatically run all our tests. They should all pass because we haven't made any changes to the generated code. If they don't, you'll need to spend time sorting out any failures before continuing.

The next step is to make the app more user friendly. We'll make a few changes now and leave the rest for you to do later.

  1. Update the layout file so it has accurate navigation. Boostrap created several dummy links in the header navigation and sidebar. Update the navigation list in /app/views/layouts/application.html.erb to include the following code:

    <a class="brand" href="/">Contestapp</a> <div class="container-fluid nav-collapse"> <ul class="nav"> <li><%= link_to "Accounts", accounts_path%></li> </ul> </div><!--/.nav-collapse -->

  2. Add validations to the account model to ensure that all fields are required when creating/updating an account. Add the following lines to /app/models/account.rb:

    validates_presence_of :shopify_account_url validates_presence_of :shopify_api_key validates_presence_of :shopify_password validates_presence_of :shopify_shared_secret

    This will immediately cause the controller tests to fail due to the fact that it is not passing in all the required fields when attempting to submit the created form.

  3. If you look at the top of the file, you'll see some code that creates the :valid_attributes hash. If you read the comment above it, you'll see that we need to update the hash to contain the following minimally required fields:

    # This should return the minimal set of attributes required # to create a valid Account. As you add validations to # Account, be sure to adjust the attributes here as well. let(:valid_attributes) { { "shopify_account_url" => "MyString", "shopify_password" => "MyString", "shopify_api_ key" => "MyString", "shopify_shared_secret" => "MyString" } }

    This is a prime example of why having a testing suite is important. It keeps us from writing code that breaks other parts of the application, or in this case, helps us discover a weakness we might not have known we had: the ability to create a new account record without filling in any fields!

  4. Now that we have satisfied this requirement and all our tests pass, we can commit the code and merge it with the master branch:

    git add --all git commit -am "Account model and related files" git checkout master git merge ch03_02_shopify_credentials git push

Excellent! We've now completed another critical piece!

Connecting to Shopify

Now that we have a test store to work with, we're ready to implement the code necessary to connect our app to Shopify.

  1. First, we need to create a topic branch:

    git checkout -b ch03_03_shopify_connection

  2. We are going to use the official Shopify gem to connect our app to our test store, as well as interact with the API. Add this to the Gemfile under the gem 'bootstrap-sass' line:

    gem 'shopify_api'

  3. Update the bundle from the command line:

    bundle install

We'll also need to restart Guard in order for it to pick up the new gem. This is typically done by using a key combination like Ctrl + Z< (Windows) or Cmd + C (Mac OS X) or by typing the word exit and pressing the Enter key.

I've written a class that encapsulates the Shopify connection logic and initializes the global ShopifyAPI class that we can then use to interact with the API. You can find the code for this class in ch03_shopify_integration.rb. You'll need to copy the contents of this file to your app in a new file located at /app/services/shopify_integration.rb. The contents of the spec file ch03_shopify_integration_spec.rb need to be pasted in a new file located at /spec/services/shopify_integration_spec.rb. Using this class will allow us to execute something like ShopifyAPI::Order.find(:all) to get a list of orders, or ShopifyAPI::Product.find(1234) to retrieve the product with the ID 1234.

The spec file contains tests for functionality that we haven't built yet and will initially fail. We'll fix this soon!

We are going to add a Test Connection button to the account page that will give the user instant feedback as to whether or not the credentials are valid. Because we will be adding a new action to our application, we will need to first update controller, request, routing, and view tests before proceeding. Given the nature of this article and because in this case, we're connecting to an external service, the topics such as mocking, test writing, and so on will have to be reviewed as homework. I recommend watching the excellent screencasts created by Ryan Bates at http://railscasts.com as a primer on testing in Rails.

  1. The first step is to update the resources :accounts route in the /config/routes.rb file with the following block:

    resources :accounts do member do get 'test_connection' end end

  2. Copy the controller code from ch03_accounts_controller.rb and replace the code in /app/controllers/accounts_controller.rb file. This new code adds the test_connection method as well as ensuring the account is loaded properly.

  3. Finally, we need to add a button to /app/views/account/show.html.erb that will call this action in div.form-actions:

    <%= link_to "Test Connection",test_connection_account_path
    (@account), :class => 'btn' %>

  4. If we view the account page in our browser, we can now test our Shopify integration. Assuming that everything was copied correctly, we should see a success message after clicking on the Test Connection button. If everything was not copied correctly, we'll see the message that the Shopify API returned to us as a clue to what isn't working.

  5. Once all the tests pass, we can commit the code and merge it with the master branch:

    git add --all git commit -am "Shopify connection and related UI" git checkout master git merge ch03_03_shopify_connection git push

Having fun? Good, because things are about to get heavy.

Summary:

As you can see and understand this article explains briefly about, the integration with Shopify's API in order to retrieve product and order information from the shop. The UI is then streamlined a bit before the logic to create a contest is created.

Resources for Article:


Further resources on this subject: