Episodes
stephen.schuez PRO said about 1 month ago on Hotwire Question and Answer Feature :
Thanks for this, this is gold. I’ve been banging my head against authorizations with broadcasting and, in the end, came up with a front-end solution. I basically put some info into the head about the current user:
<meta name="current-person-id" content="<%= current_user ? current_user.id : nil %>">
<meta name="current-person-admin" content="<%= current_user ? current_user.admin : nil %>">
<meta name="current-person-user" content="<%= @workout&.user == current_user ? true : nil %>">
Then I use this info in a stimulus controller, which shows/hides elements based on what user is present.
import { Controller } from "@hotwired/stimulus"

// Connects to data-controller="meta"
export default class extends Controller {
  static targets = [ "admin", "user", "published" ]

  connect() {
    // Data from meta tags
    const admin = document.querySelector('meta[name="current-person-admin"]').content
    const user = document.querySelector('meta[name="current-person-user"]').content
    const id = document.querySelector('meta[name="current-person-id"]').content
    const published = document.querySelector('meta[name="current-record-published"]').content
    const recordId = document.querySelector('meta[name="current-record-id"]').content
    
    checkAuthorisation(this.userTargets, user)
    checkAuthorisation(this.adminTargets, admin)
    checkAuthorisationPublished(this.publishedTargets, user)

    // Check if user owns record or if user is admin
    function checkAuthorisation(elements, subject) {
      elements.forEach((element) => {
        if (subject === "true" || admin === "true") {
          // Do nothing
          // element.classList.remove("hidden")
        } else {
          element.classList.add("hidden")
        }
      })
    }

    // Check if record is published, user owns record or if user is admin
    function checkAuthorisationPublished(elements, subject) {
      elements.forEach((element) => {
        if (subject === "true" || admin === "true" || published === "true") {
          // Do nothing
          // element.classList.remove("hidden")
        } else {
          element.classList.add("hidden")
        }
      })
    }
    
  }
}
On the view, I just traget the relevant elements e.g:
<%= button_to workout_block_path(block.workout, block), method: :delete, data: { controller: "meta", target: "meta.published" }, form: { data: { turbo_confirm: "Are you sure?" } }, class: "btn-styling" do %>
  <span class="emoji">🗑</span> 
<% end %>
I’m going to give your solution a spin, which is a super creative use of the framework and which seems way more robust!! Thanks again.

P.s. this is app

itsterry PRO said about 1 month ago on Hotwire Question and Answer Feature :
Great episode: thanks Dave!

Stephane PAQUET PRO said 23 days ago on Hotwire Question and Answer Feature :
Very quick question regarding the answers route.
Why not adding shallow: true to it so that edit and delete can be performed by just knowing the answer id. After the answer is created, there is no need to carry the question id when it comes to edit or delete it, no?

David Kimura PRO said 23 days ago on Hotwire Question and Answer Feature :
You can go that route for sure. Personally, I don't like the off chances that an answer could be updated for a different question by accident (if someone is changing the form values via inspect elements). 

pitosalas PRO said 14 days ago on Hotwire Question and Answer Feature :
I haven't used your "template" starting point before. It seems to have devise built in and some generator bootstrap magic. I am sure much more. Can you point me to any doc about it? Thanks.

David Kimura PRO said 14 days ago on Hotwire Question and Answer Feature :
The template is really geared to just set up some basic things. I have a repo https://github.com/driftingruby/template with the template that I use.

I also use a .railsrc file which will set a few defaults whenever I create a new Rails app.

# ~/.railsrc
--skip-jbuilder
--javascript esbuild
--css bootstrap

The basic devise install is another template that I have an alias for to apply to an existing template application.

gem 'devise'
run 'bundle install'
generate('devise:install')
generate(:devise, 'User')

environment 'config.action_mailer.default_url_options = { host: "localhost", port: 3000 }', env: 'development'

append_to_file 'app/views/layouts/_navigation_links.html.erb' do
  <<~'HEREDOC'

  <% if user_signed_in? %>
    <li class="nav-item me-4">
      <%= link_to "My Account", edit_user_registration_path, class: "nav-link" %>
    </li>
    <li class="nav-item me-4">
      <%= link_to "Sign Out", destroy_user_session_path, "data-turbo-method": :delete, class: "nav-link" %>
    </li>
  <% else %>
    <li class="nav-item me-4">
      <%= link_to "Sign In", new_user_session_path, class: 'nav-link' %>
    </li>
  <% end %>
  HEREDOC
end

rake 'db:migrate'

git add: '.'
git commit: %( -m 'added devise')

Login to Comment