technology

Ruby on Rails 5 with Stripe Element Integration

This tutorial shows you how I set up Stripe Element with Ruby on Rails 5 for my project For A Piece, a job board for programmers looking for companies that offer equity. 


Setup

This project is using Ruby 2.6.1 and Rails 5.2.3. This tutorial expects you to have an initial Rails app. If you’re copying&pasting, you might need to update the quotes.

Step 1.

Add gem 'stripe' to your gemfile and bundle install.

Step 2.

Add the code to your application.html.erb. I’ve added this inside the <header></header> section after <%= yield :javascript %>. I’ve added 2 environments as I do not wish to charge a real card during development. You’re going to see if/else in Step 2 and Step 3. This isn’t required and you can choose how to set up your own environment.

<%= yield :javascript %>
<%= yield :head %>
<%= javascript_include_tag 'application', "https://js.stripe.com/v2/", "https://js.stripe.com/v3/", 'data-turbolinks-track': 'reload' %>

<% if Rails.env == 'development' %>
    <%= tag :meta, name: "stripe-public-key", content: Rails.application.credentials.stripe_test[:publishable_key] %>
<% else %>
    <%= tag :meta, name: "stripe-public-key", content: Rails.application.credentials.stripe_production[:publishable_key] %>
<% end %>

Step 3.

Initialize stripe.rb. Create a file config/initializers/stripe.rb 

require "stripe"

if Rails.env == 'development'
  Rails.configuration.stripe = {
    :publishable_key => Rails.application.credentials.stripe_test[:publishable_key],
    :secret_key      => Rails.application.credentials.stripe_test[:secret_key]
  }
  Stripe.api_key = Rails.application.credentials.stripe_test[:secret_key]
else
  Rails.configuration.stripe = {
    :publishable_key => Rails.application.credentials.stripe_production[:publishable_key],
    :secret_key      => Rails.application.credentials.stripe_production[:secret_key]
  }
  Stripe.api_key = Rails.application.credentials.stripe_production[:secret_key]
end

Step 4.

Add Routes, Controller, and View. I chose Purchases, but you can call this any name that makes sense to you. 

In the routes.rb add resources: purchases, only: [:new, :create]

In the purchases_controller.rb add

class PurchasesController < ApplicationController
  def new
  end

  def create
    token = params[:stripeToken]
    if token
      Stripe::Charge.create({
        amount: '100.00',
        currency: "usd",
        description: 'your product description',
        source: token
      })
    else
      flash[:alert] = 'Something went wrong with your payment. Please try again later'
      render 'new'
    end
  end
end

In views/purchases/new.html.erb add

<%= form_tag purchases_path, id: "payment-form" do |form| %>
<div class="group">
<label>
<span>Name</span>
<input id="name" class="field" placeholder="Jane Doe" />
</label>
<label>
<span>Card</span>
<div id="card-element" class="field"></div>
</label>
</div>
<button class='subscription-button'>Place your order</button>
<div class="outcome">
<div id="card-errors" role="alert"></div>
<div class="success">
Success! Your Stripe token is <span class="token"></span>
</div>
</div>
<% end %>

Step 5

The final piece of the puzzle. Adding Javascript to stylize, embed, and submit the form. In the path assets/javascripts/subscriptions.js add

document.addEventListener("turbolinks:load", function() {
  var public_key = document.querySelector("meta[name='stripe-public-key']").content;
  var stripe = Stripe(public_key);
  var elements = stripe.elements();

// Custom styling can be passed to options when creating an Element.
  var style = {
    base: {
      // Add your base input styles here. For example:
      fontSize: '18px',
    }
  };

 // Create an instance of the card Element
  var card = elements.create('card', {style: style});
 // Add an instance of the card Element into the `card-element` <div>
  card.mount('#card-element');
  // card.mount('#example1-card');
 card.addEventListener('change', function(event) {
    var displayError = document.getElementById('card-errors');
    if (event.error) {
      displayError.textContent = event.error.message;
    } else {
      displayError.textContent = '';
    }
  });
  // Create a token or display an error when the form is submitted.
  var form = document.getElementById('payment-form');
  form.addEventListener('submit', function(event) {
    var name = document.getElementById('name').value;
    if (!name) {
      var errorElement = document.getElementById('card-errors');
      errorElement.textContent = "You must enter a name.";
      errorElement.classList.add('visible');
      return;
    } else {
      event.preventDefault();
      var options = {
        name: name,
      };
 stripe.createToken(card, options).then(function(result) {
        if (result.error) {
          // Inform the user if there was an error
          var errorElement = document.getElementById('card-errors');
          errorElement.textContent = result.error.message;
        } else {
          // Send the token to your server
          stripeTokenHandler(result.token);
        }
      });
    }
  });
}); 
 function stripeTokenHandler(token) {
  // Insert the token ID into the form so it gets submitted to the server
  var form = document.getElementById('payment-form');
  var hiddenInput = document.createElement('input');
  hiddenInput.setAttribute('type', 'hidden');
  hiddenInput.setAttribute('name', 'stripeToken');
  hiddenInput.setAttribute('value', token.id);
  form.appendChild(hiddenInput);
 ["brand", "exp_month", "exp_year", "last4"].forEach(function(field) {
    addFieldToForm(form, token, field);
  });
 // Submit the form
  form.submit();
}
 function addFieldToForm(form, token, field) {
  var hiddenInput = document.createElement('input');
  hiddenInput.setAttribute('type', 'hidden');
  hiddenInput.setAttribute('name', "user[card_" + field + "]");
  hiddenInput.setAttribute('value', token.card[field]);
  form.appendChild(hiddenInput);
} 

That’s all folks! Now when you visit purchases#new you will see a form with a name and credit card field that is already styled right on your page. No more ugly modals! 



If you’re looking for a new remote programming job that offers equity come checkout For A Piece, it’s free! 

Cheers!
John Moon

Standard
Uncategorized

Concious Effort

cartoon image of a character with an bright idea

This is my decision to get back into blogging. I’ve been meaning to write again, but life got the best of me and I’ve had no time to put my thoughts into words. There’s always some reasonable excuse. This is also true in other aspects of my life.

I have these ideas that I want to do.

Be a CEO of a successful company
Get a promotion
Learn spanish
Compete a BJJ tournament and place
Try new restaurants
Read more
Travel far and wide
Go to a movie premier and walk the red carpet.

I think about them and desire to do them. But for one reason or another, it doesn’t happen.

This brief desire is nothing more than a dream unless I make this momentary thought into conscious level effort. I need to put my thoughts into bite size steps. If I want to checkout the new restaurant with my wife, I need to find out when they open and plan a date that works for both of us. If I want to travel more, the average cost for a 4 night trip is about 144 per day. How much do I need to save and when can I go? These little thoughts are the connecting force to making dreams into reality.

The activity can be important, trivial, new, old, easy or hard. Unless there’s effort behind my thoughts it will remain a dream.

You will never find time for anything. If you want time, you must make it.

Charles Buxton

Think and Grow
John Moon

Standard
Uncategorized

Maturing As a Software Engineer

I’ve began reading the Design Patterns In Ruby book and I feel my thought process has changed over these past 3 years. And I believe I’m going through my young adulthood in programming.

I’ve learned so much as a new developer. I’ve got my first internship out of a coding bootcamp. My first junior and mid-level roles with different expectations.

As an intern was to get things done! The project manager would give me a task, and I was expected to make it work at any cost. This meant design, coding style, loading speed all went out the window. I didn’t care if it took 1 or 10  seconds to load! I just wanted to make it work.

As an junior it was to focus my learning on small things! Started thinking about good implementation. Think through ways to cache and make things faster. But still no real skills or understanding of design patterns to really make it work.

As an mid-level engineer I wanted to take ownership of projects. Building things from scratch and expressing my own design knowledge. This experience has shown me ways to write better software for maintainability and scalability. I’ve also noticed that I’ve used patterns unknowingly in my own side projects. This was the moment that I’ve realized I’ve came a long way. I picked up different habits and formed my own opinion on what is good from programmers around me.

I know road to mastery is far and full of twists and turns, I’m excited to see what else I would learn from book and those around me.

Books that I’ve really enjoyed reading this year
Confident Ruby – It’s worth the price!
– Design Pattern – Just started but this has been opening my eyes to the patterns I’ve used unknowingly

Standard
Uncategorized

Thoughts After Being Laid Off

First off, as much as layoffs sucks, it was the right move for the company. According to friends still employed there, the company is doing much better. No hard feelings.

But, the aftereffects of being laid off sucks. It’s awkward, disappointing, rejected and the works right. Also the thought of “how do I explain this to my next employer…”

It hit me that I was a disposable employee. I was powerless.

I knew leading up to the layoffs, I was relaxed. We recently launched a big initiative, where I worked around the clock and I was burnt out. I felt like I didn’t have much more to give. At this point I know that there are other employees who will and can work harder and faster to deliver what it needs.

Although, I accept the hand that was dealt to me. I promise myself that I will never put myself in this position again. I’m going to work hard and rise the corporate ladder where they need me. Not the other way around.

John

Standard
Uncategorized

2016 – Projects I’ve Worked On

I wanted to keep track of what I’ve worked on for the year. This will be updated continuously as new projects emerge.

  1. SeatGeek gem (https://github.com/jmoon90/seat_geek)
    • I’ve built this because I didn’t feel like the other gems were up to date. Many haven’t been updated since 1 or 2 years ago. 
    • Those older gems didn’t have specific SeatGeek API features I was interested in using.
      • group different type of events (sports vs concerts vs theatre) and return objects
  2. Save A Hour (http://saveahour.com/)
    • Problem: After booking a flight, travelers spend hours looking up different things to do through Yelp, sporting venues, concert venues, blog posts, etc.
    • Solution: Allow travelers to find all the info they want on one website and save them to an schedule. 
  3. Golden Coast Company (http://www.goldencoastcompany.com/) 
    • Problem: Need to sell pomade hair product to users. They need to add a shipping address and ability to make a payment. 
    • Tools: RoR, Bootstrap, Devise, Stripe
    • What I could do better: I probably didn’t need to create the address and the join address_book for Users. I later found out that Stripe allows you to capture addresses through their widget. Unless I pre-populate the Stripe form with the address the user inputed. I need to think deeply, on how the feature will help users use the product before building them out. 
This page will be continuously updated as I work on new things. If there is a specific update you wish, please let me know and I will try to update with more info.
Standard
Uncategorized

Overriding Habits

I’ve been reading “The Power of Habit” and I want to share the basic fundamentals of how habits works and what you can do in a short post.

You don’t notice it, but everything that we do stems out of habit. The scary part is our minds don’t care if it’s bad or good habits. There are just habits.

For instance, we know that smoking cigarettes can cause lung cancer and potentially take a life. However, those who smoke can’t seem to be able to stop. This is the idea of habits.

1) trigger – e.g after eating a big meal and need to digest OR when they’re in a social setting and see people smoking.
2) action – e.g they smoke
3) result /satisfaction – e.g a sense of relief or feeling of being part of the group.

What is the practical approach to stop smoking? It’s by changing the action (step 2). It’s impossible to get rid of the environment or the gratification you get. However, you can change what kind of action you take.

E.g You just ate a big meal. You’re full (trigger). Instead of smoking, how about a cup of coffee (action). Then you get that coffee high (satisfaction).

This is a basic example and may not work for everyone. But this is the idea. You want to change the action instead of the trigger or result.

I hope you learned something out of this about habit! The book pretty much builds on top of this idea and shares a lot of great examples about habits.

John.

Standard
Uncategorized

Critical Mindset For Entrepreneurs

In entrepreneurship, it’s important to have the right mindset. There will be highs and lows in each journey. Sometimes the journey sucks where you’ll have to layoff employees because of lack of growth. Other times, it’s great with a new surge of customers. For these different experiences we need to be ready to cope with the highs and lows. How do we prepare ourselves you ask? It begins with our mindset. It plays a big role in how we view these situations.

There are two mindsets Growth vs FIxed that Carol S. Dweck, Ph.D. talks about in her book Mindset: The New Psychology of Success. Individuals with a growth mindset, focuses on the journey to their goal. The characteristics of these individuals are positive attitude, not easily deterred, love challenges, and most importantly resilience. When these individuals realize their fighting an uphill battle, they look and find ways to continue forward. Even if they fail they find what they have learned and move forward.

On the other hand, fixed mindset focuses on the end result of their goal. The characteristics of these individuals are similar to the Growth mindset, expect their lack of resilience in times of trouble or failure. These individuals face failure with personal failure and crumbles. They do not gain anything from not reaching their goal and move on. There is nothing more this they can do to reach their original goal.

As entrepreneurs our journeys are unpredictable. We don’t know how our lives are going to change in a year, a month, a week from now. Our mind and body has to be ready for those volatile moments. So what can you do to get this growth mindset.

  1. Understand what type of mindset you currently have (If you’re a growth mindset, continue doing you and go to step 5)
  2. Write down accomplishments throughout your journey (This is like the highlight reel)
  3. Meditate on what you have gained, if you’re venture failed at this moment.
  4. Write down what you have learned from the experience
  5. At the end of your journey, cherish your experience and write up an another game plan to reach your goal(s).
The great news about our mindset is, it’s our mindset. We can change the way we think by practicing and catching ourselves when we slip. I know because I use to have a fixed mindset. It was all or nothing for me. I gained nothing if I lost. But rethinking about my past experiences, this couldn’t be further from the truth. I have met and gained a lot throughout my failed experiences. I hope you do too!
Think and Grow Entrepreneur
John  
Standard