Books represent most of the same premise as Houses but use a cache-key-in-URL approach to better accomodate for the down-sides of routing in-session. This helps the outside view appear to be more database-like even though the partial model persists only in the cache. We take a randomized character approach for this setup.
Title | Author name | Year published | Isbn | Primary topic | Fictionaility | |||
---|---|---|---|---|---|---|---|---|
aaefae | aefeaf | 2020 | 2 | eafeaf | eafaef | Show | Edit | Destroy |
dbf | dsfg | 1970 | 1 | asdf | asdf | Show | Edit | Destroy |
qwerty | qwerty | 1955 | 3214 | eew | eqeq | Show | Edit | Destroy |
qwerty | qwerty | 1995 | 21121 | qwerty | qwerty | Show | Edit | Destroy |
Rrr | Trt | 2232 | 23659852 | Rr | Ggg | Show | Edit | Destroy |
adsads | adsdsa | 34243 | 2342443 | dsads | dsaads | Show | Edit | Destroy |
ff | df | 1987 | 2345 | af | Show | Edit | Destroy | |
test | john | 1980 | 333 | fiction | Show | Edit | Destroy | |
32 | 3232 | 2020 | 4 | a | dsds | Show | Edit | Destroy |
Some | some | 1990 | 3123 | sdasdasd | dasdasdasd | Show | Edit | Destroy |
sdfsf | sdfsdf | 1992 | 2 | dfgdf | dfgdfg | Show | Edit | Destroy |
eee | eee | 2002 | 1 | 1 | 1 | Show | Edit | Destroy |
book | rrrrr | 1988 | 23 | etsgfbsfdb | bsdbvdfsb | Show | Edit | Destroy |
Mr Fox | Fox | 2001 | 123123 | 123 | 123 | Show | Edit | Destroy |
Oz | Wizard | 2019 | 38388392 | Wiz of Oz | Highly fictional | Show | Edit | Destroy |
thing | thingy | 2021 | something | else | Show | Edit | Destroy | |
book1 | author1 | 2000 | 12312 | test | tset | Show | Edit | Destroy |
Quia eos sequi aut e | Wing Mann | 2000 | 54 | Consequatur Suscipi | Autem vel autem volu | Show | Edit | Destroy |
aads | asdasdas | 2000 | 1 | dsadsa | asdsa | Show | Edit | Destroy |
Culpa ut velit nece | Kameko Nielsen | 2000 | 8 | Ex dolore id minima | Adipisicing autem in | Show | Edit | Destroy |
kevdog | kevin | 2022 | asdfadsf | Show | Edit | Destroy | ||
JL | Joao | 2000 | 22 | Scince | sast | Show | Edit | Destroy |
asdf | 2f23f | 1981 | 1231231233 | f32f | 23f23f | Show | Edit | Destroy |
Perica | Pera | 1999 | 123 | Other | None | Show | Edit | Destroy |
Poiuy | Azerty | 1985 | Topic | Yes | Show | Edit | Destroy | |
dictionary | bob | 1999 | aaa | a | Show | Edit | Destroy | |
Unga | Bunga | 2022 | 1234 | Self-Improvement | DER | Show | Edit | Destroy |
Abc | Def | 2000 | 2 | abc | def | Show | Edit | Destroy |
New book | Sizzle | 1981 | 273727 | Gems | Non | Show | Edit | Destroy |
Test | Sean | 2006 | 123456 | Fishing | Non-Fiction | Show | Edit | Destroy |
Foo | Bar | 1999 | 12312341 | Foo | Bar | Show | Edit | Destroy |
sdf | sdf | 1980 | 4 | dsf | sdf | Show | Edit | Destroy |
aer | aer | 5134 | 0 | aer | aer | Show | Edit | Destroy |
test | test | 2222 | 22 | 1 | 1 | Show | Edit | Destroy |
dsdasd | asdasd | 2022 | sad | dsds | Show | Edit | Destroy | |
The Great Jeffsky | Jeff Knox | 2022 | 1234567 | Jeff Knox Life | Non Fiction | Show | Edit | Destroy |
Test | Nicolas | 2012 | 23123 | yes | Show | Edit | Destroy | |
The Shiz | Bobby D | 1990 | 12121212 | Bizzness | It's all true | Show | Edit | Destroy |
23 | 23 | 2023 | 23 | 32 | Show | Edit | Destroy |
# Generated from
# rails g scaffold Book title author_name year_published:integer isbn:integer primary_topic fictionaility
class Book < ApplicationRecord
FORM_TURBO_FRAME_ID = 'book_multi_step_form'
enum form_steps: {
basics: [:title, :author_name],
organizational: [:year_published, :isbn],
details: [:primary_topic, :fictionaility]
}
attr_accessor :form_step
with_options if: -> { required_for_step?(:basics) } do
validates :title, presence: true
validates :author_name, presence: true
end
with_options if: -> { required_for_step?(:organizational) } do
validates :year_published, presence: true, numericality: { greater_than: 1950 }
# isbn not required
end
with_options if: -> { required_for_step?(:details) } do
# primary topic not required
validates :fictionaility, presence: true
end
# Checks current step to enable or disable validations appropriately
def required_for_step?(step)
# All fields are required if no form step is present
return true if form_step.nil?
# All fields from previous steps are required
ordered_keys = self.class.form_steps.keys.map(&:to_sym)
!!(ordered_keys.index(step) <= ordered_keys.index(form_step))
end
end
resources :books
resources :build_book, only: [] do
resources :step, only: [:update, :show], controller: 'steps_controllers/book_steps'
end
class BooksController < ApplicationController
before_action :set_book, only: %i[ show edit update destroy ]
# GET /books or /books.json
def index
@books = Book.all
end
# GET /books/1 or /books/1.json
def show
end
# GET /books/new
def new
book_builder_key = Random.urlsafe_base64(6) # Only non-vanilla-Rails code here
Rails.cache.fetch(book_builder_key) { Hash.new } # Only non-vanilla-Rails code here
redirect_to build_book_step_path(book_builder_key, Book.form_steps.keys.first) # Only non-vanilla-Rails code here
end
# GET /books/1/edit
def edit
end
# POST /books or /books.json
def create
@book = Book.new(book_params)
respond_to do |format|
if @book.save
format.html { redirect_to @book, notice: "Book was successfully created." }
format.json { render :show, status: :created, location: @book }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @book.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /books/1 or /books/1.json
def update
respond_to do |format|
if @book.update(book_params)
format.html { redirect_to @book, notice: "Book was successfully updated." }
format.json { render :show, status: :ok, location: @book }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @book.errors, status: :unprocessable_entity }
end
end
end
# DELETE /books/1 or /books/1.json
def destroy
@book.destroy
respond_to do |format|
format.html { redirect_to books_url, notice: "Book was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_book
@book = Book.find(params[:id])
end
# Only allow a list of trusted parameters through.
def book_params
params.require(:book).permit(:title, :author_name, :year_published, :isbn, :primary_topic, :fictionaility)
end
end
module StepsControllers
class BookStepsController < ApplicationController
include Wicked::Wizard
steps *Book.form_steps.keys
def show
book_attrs = Rails.cache.read params[:build_book_id]
@book = Book.new book_attrs
render_wizard
end
def update
book_attrs = Rails.cache.read(params[:build_book_id]).merge book_params
@book = Book.new book_attrs
if @book.valid?
Rails.cache.write params[:build_book_id], book_attrs
redirect_to_next next_step
else
render_wizard nil, status: :unprocessable_entity
end
end
private
def book_params
params.require(:book).permit(Book.form_steps[step]).merge(form_step: step.to_sym)
end
def finish_wizard_path
book_attrs = Rails.cache.read(params[:build_book_id])
@book = Book.new book_attrs
@book.save!
Rails.cache.delete params[:build_book_id]
book_path(@book)
end
end
end
<%= turbo_frame_tag dom_id(@book) do %>
<%= form_with model: @book, url: wizard_path, method: :patch do |f| %>
<% if f.object.errors.any? %>
<div class="error_messages">
<% f.object.errors.full_messages.each do |error| %>
<p><%= error %></p>
<% end %>
</div>
<% end %>
<fieldset>
<legend>Book Basics</legend>
<div>
<%= f.label :title %>
<%= f.text_field :title %>
</div>
<div>
<%= f.label :author_name %>
<%= f.text_field :author_name %>
</div>
<br/>
<div>
<%= link_to 'Nevermind', books_path, data: { turbo_frame: :_top } %> <%# NOTE the _top target %>
<%= f.submit 'Next Step' %>
</div>
</fieldset>
<% end %>
<% end %>
<%= turbo_frame_tag dom_id(@book) do %>
<%= form_with model: @book, url: wizard_path, method: :patch do |f| %>
<% if f.object.errors.any? %>
<div class="error_messages">
<% f.object.errors.full_messages.each do |error| %>
<p><%= error %></p>
<% end %>
</div>
<% end %>
<fieldset>
<legend>Book Organizing Details</legend>
<div>
<%= f.label :year_published %>
<%= f.number_field :year_published %>
</div>
<div>
<%= f.label :isbn %>
<%= f.number_field :isbn %>
</div>
<br/>
<div>
<%= link_to 'Previous Step', previous_wizard_path %>
<%= f.submit 'Continue' %>
</div>
</fieldset>
<% end %>
<% end %>
<%= turbo_frame_tag dom_id(@book) do %>
<%= form_with model: @book, url: wizard_path, method: :patch, data: { turbo_frame: :_top } do |f| %> <%# NOTE the _top target %>
<% if f.object.errors.any? %>
<div class="error_messages">
<% f.object.errors.full_messages.each do |error| %>
<p><%= error %></p>
<% end %>
</div>
<% end %>
<fieldset>
<legend>Book Details</legend>
<div>
<%= f.label :primary_topic %>
<%= f.text_field :primary_topic %>
</div>
<div>
<%= f.label :fictionaility %>
<%= f.text_field :fictionaility %>
</div>
<br/>
<div>
<%= link_to 'Previous Step', previous_wizard_path %>
<%= f.submit 'Complete' %>
</div>
</fieldset>
<% end %>
<% end %>