Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FFM-6926 - Add basic Ruby on Rails example #15

Merged
merged 3 commits into from
Feb 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ Further examples and config options are in the further reading section:

[Further Reading](docs/further_reading.md)

[Ruby on Rails example](ruby_on_rails_example/README.md)

-------------------------
[Harness](https://www.harness.io/) is a feature management platform that helps teams to build better software and to
Expand Down
7 changes: 7 additions & 0 deletions ruby_on_rails_example/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# See https://git-scm.com/docs/gitattributes for more about git attribute files.

# Mark the database schema as having been generated.
db/schema.rb linguist-generated

# Mark any vendored files as having been vendored.
vendor/* linguist-vendored
35 changes: 35 additions & 0 deletions ruby_on_rails_example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
# git config --global core.excludesfile '~/.gitignore_global'

# Ignore bundler config.
/.bundle

# Ignore the default SQLite database.
/db/*.sqlite3
/db/*.sqlite3-*

# Ignore all logfiles and tempfiles.
/log/*
/tmp/*
!/log/.keep
!/tmp/.keep

# Ignore pidfiles, but keep the directory.
/tmp/pids/*
!/tmp/pids/
!/tmp/pids/.keep

# Ignore uploaded files in development.
/storage/*
!/storage/.keep
/tmp/storage/*
!/tmp/storage/
!/tmp/storage/.keep

/public/assets

# Ignore master key for decrypting credentials and more.
/config/master.key
1 change: 1 addition & 0 deletions ruby_on_rails_example/.ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2.7.7
9 changes: 9 additions & 0 deletions ruby_on_rails_example/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM ruby:2.7.7
RUN apt-get update && apt-get install -y build-essential nodejs
RUN mkdir -p /app
WORKDIR /app
COPY Gemfile Gemfile.lock ./
RUN gem install bundler && bundle install --jobs 10 --retry 3
COPY . ./
EXPOSE 3000
CMD ["rails", "s", "-b", "0.0.0.0"]
74 changes: 74 additions & 0 deletions ruby_on_rails_example/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby "2.7.7"

# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
gem "rails", "~> 7.0.4", ">= 7.0.4.2"

# The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]
gem "sprockets-rails"

# Use sqlite3 as the database for Active Record
gem "sqlite3", "~> 1.4"

# Use the Puma web server [https://github.com/puma/puma]
gem "puma", "~> 5.0"

# Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails]
gem "importmap-rails"

# Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]
gem "turbo-rails"

# Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]
gem "stimulus-rails"

# Build JSON APIs with ease [https://github.com/rails/jbuilder]
gem "jbuilder"

# Use Redis adapter to run Action Cable in production
gem "redis", "~> 4.0"

# Use Kredis to get higher-level data types in Redis [https://github.com/rails/kredis]
# gem "kredis"

# Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword]
# gem "bcrypt", "~> 3.1.7"

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem "tzinfo-data", platforms: %i[ mingw mswin x64_mingw jruby ]

# Reduces boot times through caching; required in config/boot.rb
gem "bootsnap", require: false

# Use Sass to process CSS
# gem "sassc-rails"

# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
# gem "image_processing", "~> 1.2"

gem 'ff-ruby-server-sdk', '>= 1.0.6'

group :development, :test do
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
gem "debug", platforms: %i[ mri mingw x64_mingw ]
end

group :development do
# Use console on exceptions pages [https://github.com/rails/web-console]
gem "web-console"

# Add speed badges [https://github.com/MiniProfiler/rack-mini-profiler]
# gem "rack-mini-profiler"

# Speed up commands on slow machines / big apps [https://github.com/rails/spring]
# gem "spring"
end

group :test do
# Use system testing [https://guides.rubyonrails.org/testing.html#system-testing]
gem "capybara"
gem "selenium-webdriver"
gem "webdrivers"
end
31 changes: 31 additions & 0 deletions ruby_on_rails_example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Ruby on Rails example

This basic project shows how to use the Ruby SDK in a Rails (2.7.x) application.

### Build the docker image

```bash
docker build -t rails-example .
```

### Run docker image

```bash
export FF_API_KEY=<your server SDK key>
docker run -e FF_API_KEY=$FF_API_KEY -p 3000:3000 --rm rails-example
```

### Access web server

http://localhost:3000/

When you toggle a flag on https://app.harness.io it will be logged in the console output of the container. Since this is a server SDK you need to refresh the page in the browser to see the HTML update.


### Main files

[Controller](app/controllers/example_controller.rb)

[View](app/views/example/index.html.erb)

[Helper](app/helpers/example_helper.rb)
6 changes: 6 additions & 0 deletions ruby_on_rails_example/Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.

require_relative "config/application"

Rails.application.load_tasks
4 changes: 4 additions & 0 deletions ruby_on_rails_example/app/assets/config/manifest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//= link_tree ../images
//= link_directory ../stylesheets .css
//= link_tree ../../javascript .js
//= link_tree ../../../vendor/javascript .js
Empty file.
15 changes: 15 additions & 0 deletions ruby_on_rails_example/app/assets/stylesheets/application.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS (and SCSS, if configured) file within this directory, lib/assets/stylesheets, or any plugin's
* vendor/assets/stylesheets directory can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
* compiled file so the styles you add here take precedence over styles defined in any other CSS
* files in this directory. Styles in this file should be added after the last require_* statement.
* It is generally better to create a new file per style scope.
*
*= require_tree .
*= require_self
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module ApplicationCable
class Channel < ActionCable::Channel::Base
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module ApplicationCable
class Connection < ActionCable::Connection::Base
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class ApplicationController < ActionController::Base
end
Empty file.
7 changes: 7 additions & 0 deletions ruby_on_rails_example/app/controllers/example_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class ExampleController < ApplicationController

def index
@flag_name = ENV['FF_FLAG_NAME'] || 'harnessappdemodarkmode'
@target = Target.new("RubyOnRailsExample", identifier="rubysdk", attributes={"username": "test"})
end
end
2 changes: 2 additions & 0 deletions ruby_on_rails_example/app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module ApplicationHelper
end
37 changes: 37 additions & 0 deletions ruby_on_rails_example/app/helpers/example_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
module ExampleHelper

def make_ff_client
$stdout.sync = true
logger = Logger.new $stdout
logger.level = 'info'


api_key = ENV['FF_API_KEY'] || 'changeme'

client = CfClient.instance
client.init(api_key, ConfigBuilder.new.logger(logger).build)
client.wait_for_initialization

logger.info "---- CfClient ready ----"

client
end

# Use this to access the CfClient.instance - it will make sure it's only instantiated once
def get_ff_client
@@ff_client ||= make_ff_client

@@ff_client
end


# A helper method that gets and logs the flag state
def get_bool_flag(flag_name, target, default)
value = get_ff_client.bool_variation(flag_name, target, default)

logger.info "FLAG %s ---> %s" % [flag_name, value]

value
end

end
3 changes: 3 additions & 0 deletions ruby_on_rails_example/app/javascript/application.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
import "@hotwired/turbo-rails"
import "controllers"
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Application } from "@hotwired/stimulus"

const application = Application.start()

// Configure Stimulus development experience
application.debug = false
window.Stimulus = application

export { application }
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
connect() {
this.element.textContent = "Hello World!"
}
}
11 changes: 11 additions & 0 deletions ruby_on_rails_example/app/javascript/controllers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Import and register all your controllers from the importmap under controllers/*

import { application } from "controllers/application"

// Eager load all controllers defined in the import map under controllers/**/*_controller
import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading"
eagerLoadControllersFrom("controllers", application)

// Lazy load controllers as they appear in the DOM (remember not to preload controllers in import map!)
// import { lazyLoadControllersFrom } from "@hotwired/stimulus-loading"
// lazyLoadControllersFrom("controllers", application)
7 changes: 7 additions & 0 deletions ruby_on_rails_example/app/jobs/application_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class ApplicationJob < ActiveJob::Base
# Automatically retry jobs that encountered a deadlock
# retry_on ActiveRecord::Deadlocked

# Most jobs are safe to ignore if the underlying records are no longer available
# discard_on ActiveJob::DeserializationError
end
4 changes: 4 additions & 0 deletions ruby_on_rails_example/app/mailers/application_mailer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class ApplicationMailer < ActionMailer::Base
default from: "from@example.com"
layout "mailer"
end
3 changes: 3 additions & 0 deletions ruby_on_rails_example/app/models/application_record.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class ApplicationRecord < ActiveRecord::Base
primary_abstract_class
end
Empty file.
4 changes: 4 additions & 0 deletions ruby_on_rails_example/app/views/example/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<h1>Ruby on Rails FF Example</h1>

<p>Flag &quot;<%= @flag_name %>&quot; is <b> <%= get_bool_flag(@flag_name, @target, false) %></b> </p>
<p>(server example - refresh page to update)</p>
16 changes: 16 additions & 0 deletions ruby_on_rails_example/app/views/layouts/application.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<title>FfSdkExample</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>

<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_importmap_tags %>
</head>

<body>
<%= yield %>
</body>
</html>
13 changes: 13 additions & 0 deletions ruby_on_rails_example/app/views/layouts/mailer.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
/* Email styles need to be inline */
</style>
</head>

<body>
<%= yield %>
</body>
</html>
1 change: 1 addition & 0 deletions ruby_on_rails_example/app/views/layouts/mailer.text.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<%= yield %>
4 changes: 4 additions & 0 deletions ruby_on_rails_example/bin/rails
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env ruby
APP_PATH = File.expand_path("../config/application", __dir__)
require_relative "../config/boot"
require "rails/commands"
4 changes: 4 additions & 0 deletions ruby_on_rails_example/bin/rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env ruby
require_relative "../config/boot"
require "rake"
Rake.application.run
33 changes: 33 additions & 0 deletions ruby_on_rails_example/bin/setup
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env ruby
require "fileutils"

# path to your application root.
APP_ROOT = File.expand_path("..", __dir__)

def system!(*args)
system(*args) || abort("\n== Command #{args} failed ==")
end

FileUtils.chdir APP_ROOT do
# This script is a way to set up or update your development environment automatically.
# This script is idempotent, so that you can run it at any time and get an expectable outcome.
# Add necessary setup steps to this file.

puts "== Installing dependencies =="
system! "gem install bundler --conservative"
system("bundle check") || system!("bundle install")

# puts "\n== Copying sample files =="
# unless File.exist?("config/database.yml")
# FileUtils.cp "config/database.yml.sample", "config/database.yml"
# end

puts "\n== Preparing database =="
system! "bin/rails db:prepare"

puts "\n== Removing old logs and tempfiles =="
system! "bin/rails log:clear tmp:clear"

puts "\n== Restarting application server =="
system! "bin/rails restart"
end
Loading