Trying to learn this a bit, but keep running into new issues.
Currently, I have an 'explore' button that is supposed to run some controller code, and pop out a new _partial where it counts down and shows a new button. After the countdown, the 'complete' button is active and you press it, and it reupdates the #exploration contents and updates the user-info-land.
When I press the button, it doesn't work: see below.
Heres my controller:
class ExplorationController < ApplicationController
before_action :authenticate_user!
def status
render partial: 'exploration_widget', locals: { user: current_user }
end
def explore
timenow = Time.current
if current_user.is_exploring
redirect_to root_path, notice: "You are already exploring"
else
@explore_time = exploration_time
if current_user.update(explore_start: timenow, explore_end: timenow + @explore_time, is_exploring: true)
current_user.user_notifications.create(notification_id: 2, date1: timenow, date2: timenow + @explore_time)
respond_to do |format|
format.html { redirect_to root_path }
format.turbo_stream { render partial: 'exploration_widget', locals: { user: current_user } }
end
else
render plain: "Failed to update user", status: :internal_server_error
end
end
end
def complete
if current_user.explore_end <= Time.current
current_user.increment!(:land)
current_user.update(is_exploring: false)
respond_to do |format|
format.html { redirect_to root_path, notice: 'Exploration complete! You gained 1 land.' }
format.turbo_stream { render partial: 'exploration_widget', locals: { user: current_user } }
end
else
render plain: 'Exploration not yet complete.', status: :bad_request
end
end
private
def exploration_time
10.seconds
end
end
And my view/exploration/
complete.turbo_stream.erb
<turbo-stream action="replace" target="exploration">
<template>
<%= render 'exploration_widget', user: current_user %>
</template>
</turbo-stream>
<turbo-stream action="update" target="user-info-land">
<template>
<%= current_user.land %>
</template>
</turbo-stream>
explore.turbo_stream.erb
<turbo-stream action="replace" target="exploration">
<template>
<%= render 'exploration_widget', user: current_user %>
</template>
</turbo-stream>
views/shared/_exploration_widget.html.haml
%turbo-frame#exploration
- if user.is_exploring?
%div{"data-controller" => "exploration", "data-exploration-end-time-value" => "#{user.explore_end.iso8601}"}
= form_with url: complete_exploration_path, method: :post, local: true, data: { turbo_frame: "exploration" } do
%button.btn.btn-secondary{"data-exploration-target" => "completeButton", :disabled => "disabled"} Complete
#exploration-timer
Time remaining:
%span#time-remaining{"data-end-time" => "#{user.explore_end.iso8601}", "data-exploration-target" => "timeRemaining"}= time_remaining(user.explore_end)
- else
= form_with url: start_exploration_path, method: :post, local: true, data: { turbo_frame: "exploration" } do
= submit_tag 'Explore', class: 'btn btn-primary'
And my routes:
Rails.application.routes.draw do
get 'test/index'
root 'home#index'
get 'structures', to: 'structures#index'
post 'start_exploration', to: 'exploration#explore'
post 'complete_exploration', to: 'exploration#complete'
get 'exploration/status', to: 'exploration#status'
resources :armies do
post 'recruit', on: :collection
end
devise_for :users, controllers: {
omniauth_callbacks: 'users/omniauth_callbacks'
}
end
And the error in rails server:
ActionView::MissingTemplate - Missing partial exploration/_exploration_widget, application/_exploration_widget with {:locale=>[:en], :formats=>[:turbo_stream], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :haml, :jbuilder]}.
It seems like it should be working. I'm at a loss. If anyone can take a look and spot what is wrong here, thank you!
local: true
is a Rails UJS attribute and is not used by Turbo.
%turbo-frame#exploration
also not needed, because your responses are turbo streams and you don't seem to actually use this frame anywhere else, you can replace it with a div
.
format.turbo_stream
has to render a turbo stream, make sure you point to the correct partial:
# note that `partial: 'exploration_widget'` will use you current controller name
# to find the partial: `exploration/_exploration_widget`
# if you have it in a different directory you need to specify it
# `partial: 'shared/exploration_widget'`
respond_to do |format|
format.html { redirect_to root_path }
format.turbo_stream do
render turbo_stream: turbo_stream.replace(
'exploration',
partial: 'shared/exploration_widget',
locals: {user: current_user}
)
end
end
or leave it as format.turbo_stream
(without a block) to render a corresponding {action_name}.turbo_stream.erb
view:
respond_to do |format|
format.html { redirect_to root_path }
format.turbo_stream
end