Rails spina and devise
I want to have a FAQ page on my site which is editable from a CMS ie not a code redeploy.
Spina CMS
https://spinacms.com/ a local CMS that plugs into Rails.
# no!
# bundle add spina
gem 'spina', '~> 2.18'
# limited to the gems in Gemfile
bundle update
# handles file uploads (default is in /storage)
rails active_storage:install
# spina:install is rake task runner notation
rails spina:install
# name of website
# default theme
# user - we'll change this
# password - we'll change this
# routes.rb
# move this this to the bottom so we still have our normal website, and only do CMS for specific pages
# try spina routes last
mount Spina::Engine => '/'
# http://localhost:3000/admin
Create a FAQs Page
# create new page in CMS
# put in text
# check route is /faqs
# test it works but style will need changed
- views/layouts/default/application.html.erb - spina application template. Renders _nav. I’ve made this a copy of the one below
- views/layouts/application.html.erb - rails application template. Renders _nav
- views/layouts/_nav.html.erb - nav partial
in spina
- views/default/pages/show.html.erb - h1, render summary, buttons, layout, render text etc.. wrapped by spina application template
in rails
- views/default/home/dave.html.erb - page content. which is wrapped by rails application template
Customise Backend
Lets customise and make a repeater, so we’ve got full control of the css, but can change any of the text.
# this is where we define our content types.
# /config/themes/default.rb
# create a new part called summary
theme.parts = [
{name: "text", title: "Body", hint: "Your main content", part_type: "Spina::Parts::Text"},
{name: "summary", title: "Summary", hint: "A summary for your page", part_type: "Spina::Parts::Line"}
]
# create a new view template called faq which has the new summary part
theme.view_templates = [
{name: "homepage", title: "Homepage", parts: %w[text]},
{name: "show", title: "Page", parts: %w[text]},
{name: "faq", title: "FAQ", parts: %w[ummary text]}
]
# notice I need a new template called faq
Render on Frontend
<!-- views/default/pages/faq.html.erb -->
<!-- faqs is using this template -->
<h1 class="text-3xl"><%= current_page.title %></h1>
<p class="text-xl">
<%= current_page.content(:summary) %>
</p>
<!-- this renders the divs etc that the editor puts in -->
<%=content.html(:text)%>
Deploy to Production
I tried a few ways to get this right
A vanilla deploy without any data write to 2 tables
- ar_internal_metadata (1 rows) environment = production!
- schema_migrations (23 rows)
- spina_ are all empty which is bad as I need a way to login!
So lets just do a raw SQL dump from dev and run on prod. Except for ar_internal_metadata and schema_migrations
# in secrets directory
pg_dump -U postgres -d golfsubmit_development --clean --exclude-table=ar_internal_metadata --exclude-table=schema_migrations -f - | sed 's/OWNER TO dave/OWNER TO golfsubmit/g' > dev_backup.sql
# scp to server
# run
psql -U postgres -d golfsubmit_production -f /home/dave/secrets/dev_backup.sql
useful commands:
sudo -iu postgres
psql
\c golfsubmit_development
\dt # show all tables
Use Devise for Auth into Spina
# config/initializers/bigauth.rb
# Used as Spina's authentication module
module BigAuth
extend ActiveSupport::Concern
included do
helper_method :current_spina_user
helper_method :logged_in?
helper_method :logout_path
end
# Spina user falls back to devise user session in the case there is one and it is of a superadmin.
def current_spina_user
Spina::Current.user ||= current_user if current_user.is_admin?
end
# Returns falsy unless there is a logged in superadmin
def logged_in?
return current_spina_user if user_signed_in?
false
end
# Not used
def logout_path
spina.admin_logout_path
end
private
# Redirects user to sign in if not logged in as a superadmin
def authenticate
redirect_to "/login" unless logged_in?
end
end
then
# user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, #:registerable,
:recoverable, :rememberable, :validatable
def is_admin?
return true if email =="davemateer@gmail.com"
return true if email =="foo@gmail.com"
end
end
then
#initializers/spina.rb
config.authentication = "BigAuth"