fbpx

Building A Simple Landing Page With FaaStRuby Functions

What we will learn here

UPDATE March 12, 2019 - This tutorial is outdated and we're working to update it to work with FaaStRuby 0.5. In the meantime check out our legacy documentaion here.

Hi folks! I want to share with you one of the most emerging technologies for Cloud Computing. I'm talking about "Functions as a Service" or FaaS. In this article I want you to explore with me an introductory solution. We will build a serverless application, step by step, using the FaaStRuby platform, and we will make the solution available in the cloud.

FaaStRuby is an incredible platform that allows us to work in an easy way with serverless functions. The platform is intuitive and very reminiscent of Heroku, where the entire server infrastructure is abstracted. If you're not familiar with these terms, do not worry, we'll describe more about FaaStRuby, FaaS, and Serverless in this article.

Let's get to it!

What is Serverless?

Serverless is a software architecture model in which the provider of this type of cloud service acts as a server, provisioning all the necessary environment and dynamically managing resource allocation on the machines.

Don't we use servers in this architecture?

The term "serverless" is used because server management and capacity planning decisions are completely hidden from the developer. Serverless code can be used in conjunction with code deployed in traditional styles, such as microservices.

Alternatively, applications can be written to be purely serverless and not use servers managed by you.

Despite the term "serverless", there is at least one server involved in this solution in the cloud.

The focus is on software, not on infrastructure

The idea behind serverless it to keep infrastructure configuration completely abstracted from the software development process, do developers can focus on business logic and forget about servers, containers, proxies, etc.

What is FaaS?

FaaS is a subset of serverless. A cloud provider that offers ways to execute small snippets of code in a serverless manner can be called a FaaS provider. These code snippets are programs developed in a particular programming language. We call them "functions". Functions are immediately available to be executed by Runners as soon as you deploy them to the FaaStRuby platform.

What is a Runner?

As described in a recent FaaStRuby post: “Introducing Runners – A New Compute Construct for a Serverless Developer Experience” A Runner is a secure, stateless, always-running, state-of-the-art compute unit capable of accessing any function code instantly at the moment of execution, eliminating cold start times.

FaaS allows the developer to execute code only when it is needed, that's why we have the term "Functions as a Service". You can create functions and invoke them through events.

Are FaaS event-oriented?

Yes, it is correct to say that FaaS are event-oriented. Event, in this context, is something that triggers the function.

Examples:

  • An HTTP request that consumes some function endpoint.
  • A routine executed hourly, where the event that triggers the function is a timer.

What are FaaS good for?

Some problems that FaaS can solve:

Abstracted infrastructure

The developer does not need to get involved with concerns such as the amount of servers needed, virtual machines or containers to use.

Dynamic Scalability

The scalability requirements fall under the responsibility of the FaaS service provider. The FaaS provider is responsible for executing code and returning the data produced by the function.

Functions performed on demand

Functions are performed on demand. As soon as an event is triggered, the FaaS provider detects the event and turns on the function, allocates the required resources, and immediately shuts off the function.

Cost savings

FaaStRuby Runners are fast and run functions in milliseconds. This creates savings, since one Runner can respond to several requests to different functions per second. Besides the economy of the infrastructure itself, we also notice the reduction of operations costs, as the engineers are not required to waste time on infrastructure configuration.

What is FaaStRuby?

FaaStRuby is a Serverless Software Developer Platform for Ruby and Crystal. Its goal is to make the developers' job easier - forget about cloud, servers, containers, proxies, webservers, etc - just focus on code.

FaaStRuby does that by providing a command line tool for initializing functions and workspaces, while managing all the infrastructure required for running your applications in production in the cloud using a secure and distributed environment. Your functions will be instantly available when needed, and run as fast as your code can run.

At the time of writing, the platform allows you to create functions in Ruby 2.5.3, 2.6.0 and 2.6.1, and in Crystal 0.27.0 and 0.27.2.

To learn more about FaaStRuby visit the Onebitcode's blog (in portuguese).

What are we going to create?

Using the FaaStRuby platform, we'll create two functions in Ruby and make them quickly available on the internet.

Landing Pages

In online marketing, we use so-called landing pages to capture email for a marketing campaign.

To keep things simple, our solution won't send real emails. We will have two web pages, one where users can fill in their email. After submitting the form, the users will be taken to a thank you page, confirming the user's email.

Step by Step Function Creation

Installation

For our project, let's create a folder and enter into it.
$ mkdir faastruby 
$ cd faastruby
Perform this step only if you use the Ruby version manager, RVM:
$ faastruby/> rvm use ruby-2.6.0@marketing --ruby-version --create 
Install the gem

This gem is a CLI Tool that will make the FaaStRuby platform commands available in our terminal:

$ faastruby/> gem install faastruby
To know if it worked, let's see the gem version:

* For me this is the current version: 0.4.18

* Note that your version may be newer, as the platform is constantly being updated.

$ faastruby/> faastruby -v
0.4.18

The available commands are very well documented. To see the help type:

$ faastruby/> faastruby -h

Creating Your Workspace

At this point, you need to know how to start working with FaaStRuby. To work with functions you need to create a workspace first. Workspaces are "spaces in the cloud" where your functions will be stored. The workspaces have a unique name. This means that if you try to create a workspace that already exists, the command will return an error message warning you about this.You can only create workspaces with names that do not yet exist on the platform.

Enter your email address

At the time of creating the workspace you can enter your email. This isn't required but if you do, it's easy to reach out to you in case FaaStRuby needs to notify you about maintenances, etc.

Create the local folder

To create workspaces, use the --create-local-dir flag, which creates a local folder of the same name for your workspace.

Replace "marketing" with the name of the workspace you choose. Do the same with "my-email@mail.com" with your own e-mail.

$ faastruby/> faastruby create-workspace marketing --create-local-dir -e meu-email@mail.com
◐ Requesting credentials... Done!
Writing credentials to /Users/sergiolima/.faastruby.tor1
~ f /Users/sergiolima/.faastruby.tor1
Workspace 'marketing' created
+ d ./marketing

Checkpoint

If everything went well, you now have a workspace in the cloud … and also a local folder with the same name. You will also have a config file with the name of your workspace and your credentials. These credentials are important, and only you have access to them. In case of loss, there is no way to retrieve them.

To see the credentials that, do:

$ faastruby/> cat ~/.faastruby.tor1
"marketing": {
    "api_secret": "IFOiLuNUOz44GNeok....",
    "api_key": "335daec9f...."
  }
}%

Whenever we need to check our workspaces in the cloud, the command "list-workspace" is available. The command shows all the functions deployed to a workspace. For now we don't have any.

$ faastruby/> faastruby list-workspace marketing
The workspace 'marketing' has no functions.
Now cd into the folder we created:
$ faastruby/> cd marketing
$ faastruby/marketing/>

Creating Your First Function

Let's create the first function.

  • Your function needs to have a unique name inside your workspace.
  • A folder with the same function name will be automatically created in your local computer.
  • After initializing the function, cd into its folder.
$ faastruby/marketing/> faastruby new landing-page --runtime ruby:2.6.0
+ d landing-page
+ d landing-page/spec
+ f landing-page/spec/spec_helper.rb
+ f landing-page/spec/handler_spec.rb
+ f landing-page/README.md
+ f landing-page/Gemfile
+ f landing-page/handler.rb
+ f landing-page/faastruby.yml
◓ Installing gems... Done!

$ faastruby/marketing/> cd landing-page
$ faastruby/marketing/landing-page/>
Let's edit the file that will display the first page
  • Edit the file handler.rb created by the previous command.
  • You can use any text editor.
  • Within the file handler.rb there is the "handler" method.
  • The handler method is our entry point. This is the function's starting point.
  • Make the file, "handler.rb" look like:
# faastruby/marketing/landing-page/handler.rb
def handler event
  render html: File.read('index.html')
end
You also need to create the web page itself.

Just copy and paste the following html source code inside the file "faastruby/marketing/landing-page/index.html".

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>FaaStRuby - Serverless Platform for Ruby Developers</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css" />
  </head>
  <body>
    <section class="hero is-dark is-fullheight">
      <div class="hero-body">
        <div class="container has-text-centered">
          <div class="column is-8 is-offset-2">
            <h1 class="title"><b>FaaStRuby</b></h1>
            <h2 class="subtitle">Serverless Platform for Ruby Developers</h2>
            <form action="/marketing/thankyou-page">
              <div class="box">
                <div class="field is-grouped">
                  <p class="control is-expanded">
                    <input class="input" name="person_email" type="email" id="email"
                    placeholder="Enter your email" autofocus>
                  </p>
                  <p class="control">
                    <input name="submit_button" class="button is-info"
                    type="submit" value="Notify Me">
                  </p>
                </div>
              </div>
            </form>
          </div>
        </div>
      </div>
    </section>
  </body>
</html>
Unit tests

It's important to know:

  • FaaStRuby functions already come with Rspec as the test suite.
  • You will deploy the function soon and FaaStRuby will run this unit test or any other tests you might have written.
  • The deploy will fail if your tests fail.
  • There are ways to change this behavior, but let's leave it for now.
  • The following code is enough for your test to pass:
# faastruby/marketing/landing-page/spec/handler_spec.rb
require 'spec_helper'
require 'handler'

describe 'handler(event)' do
  let(:event) {Event.new(
    body: nil,
    query_params: {},
    headers: {},
    context: nil
  )}

  it 'should return a String' do
    body = handler(event).body
    expect(body).to be_a(String)
  end
end

Deploy

It's time to send your first function to the cloud.
  • The "deploy-to" command is used to deploy your function into the previously created workspace.
  • Before sending, "deploy-to" command runs unit tests, locally.
  • Then it builds a zip file that will be sent to the server.
  • Finally, your function will be sent to the platform and it'll be available through a URL.
$ faastruby/marketing/landing-page> faastruby deploy-to marketing
[build] Verifying dependencies
The Gemfile's dependencies are satisfied
[test] Running tests
.

Finished in 0.01215 seconds (files took 0.40262 seconds to load)
1 example, 0 failures

◐ Running 'before_deploy' tasks...  Done!
◐ Building package... Done!
◑ Deploying 'marketing/landing-page' Done!
Endpoint: https://api.tor1.faastruby.io/marketing/landing-page
Checkpoint: Checking if the function is in the workspace.
$ faastruby/marketing/landing-page> faastruby list-workspace marketing
FUNCTION     ENDPOINT                                            
landing-page https://api.tor1.faastruby.io/marketing/landing-page
Accessing the function in the cloud.

Remember: marketing is the name of the workspace I chose. Replace "marketing" with the name of your workspace. Finally, your function is available in the cloud.

In your browser, enter the URL:

https://api.tor1.faastruby.io/marketing/landing-page

Creating Your Second Function

Now, let's create the second function.

To create this second function, let's follow the same steps as the previous function.

Run the following commands to create the second function.

$ faastruby/marketing/landing-page/> cd ..
$ faastruby/marketing/> faastruby new thankyou-page --runtime ruby:2.6.0
+ d thankyou-page
+ d thankyou-page/spec
+ f thankyou-page/spec/spec_helper.rb
+ f thankyou-page/spec/handler_spec.rb
+ f thankyou-page/README.md
+ f thankyou-page/Gemfile
+ f thankyou-page/handler.rb
+ f thankyou-page/faastruby.yml
◓ Installing gems... Done!

$ faastruby/marketing/> cd thankyou-page
$ faastruby/marketing/thankyou-page/>
Let's edit the file that will display the second page.

Make the file, "handler.rb" look like:

# faastruby/marketing/thankyou-page/handler.rb
require 'erb'

def handler event
  @person_email = event.query_params['person_email']&.split('@')&.first
  render html: ERB.new(File.read('thankyou.html')).result(binding)
end
You also need to create the web page itself.

Just copy and paste the following HTML source code to your "thankyou.html" file.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>FaaStRuby - Serverless Platform for Ruby Developers</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css" />
  </head>
  <body>
		<section class="hero is-dark is-fullheight">
			<div class="hero-body">
				<div class="container has-text-centered">
					<div class="column is-6 is-offset-3">
            <h1 class="title">
              Thanks for subscribing <%= @person_email %>!
						</h1>
						<h2 class="subtitle">
							We'll notify you when we have
							a new feature or blog post about <b>FaaStRuby</b>.
						</h2>
					</div>
				</div>
			</div>
		</section>
  </body>
</html>
Unit tests

For now, the following code is enough for your test to pass:

# faastruby/marketing/thankyou-page/spec/handler_spec.rb
require 'spec_helper'
require 'handler'

describe 'handler(event)' do
  let(:event) {Event.new(
    body: nil,
    query_params: {'person_email' => 'my-email@mail.com'},
    headers: {},
    context: nil
  )}

  it 'should return a String' do
    body = handler(event).body
    expect(body).to be_a(String)
  end
end

Deploy

Now, you'll send your second function to the cloud.
$ faastruby/marketing/thankyou-page> faastruby deploy-to marketing
[build] Verifying dependencies
The Gemfile's dependencies are satisfied
[test] Running tests

Finished in 0.01316 seconds (files took 0.38502 seconds to load)
1 example, 0 failures

◐ Running 'before_deploy' tasks...  Done!
◐ Building package... Done!
◑ Deploying 'marketing/thankyou-page' Done!
Endpoint: https://api.tor1.faastruby.io/marketing/thankyou-page
Checkpoint: Checking if the function is in the workspace.
$ faastruby/marketing/thankyou-page> FUNCTION      ENDPOINT                                             
thankyou-page https://api.tor1.faastruby.io/marketing/thankyou-page
landing-page  https://api.tor1.faastruby.io/marketing/landing-page 
Accessing the function in the cloud.

Remember: marketing is the name of the workspace I chose. Replace "marketing" with the name of your workspace.

Your Landing Page is Live!

Finally, your function is available in the cloud. Access the url:

https://api.tor1.faastruby.io/marketing/landing-page

Conclusion

  • We learned what Serverless is, what "functions as a service" is, and what the FaaStRuby platform is.
  • We created a simple marketing landing page using functions deployed to FaaStRuby, showcasing how it allows developers to build their own functions without worrying about infrastructure configuration.

I hope you enjoyed the article!

Join the community

Create your own functions and serverless apps, deploy them to FaaStRuby and share them on Twitter mentioning @FaaStRubyHQ, and we will spread the word 🙂

See you on next post.

Related Links