$ rails new . -n ActiveAdminDemo -c tailwind -a propshaft --skip-test --skip-system-test
$ rails g active_admin:install --skip-users
$ rails tailwindcss:install
$ rails generate active_admin:assets
$ cat tailwind-active_admin.config.js | sed 's/require(`@activeadmin\/activeadmin\/plugin`)/require(`${activeAdminPath}\/plugin.js`)/g' > config/tailwind-active_admin.config.js
$ rm tailwind-active_admin.config.js
$ bundle binstub tailwindcss-rails
$ rails generate active_admin:views
I get asked pretty regularly what my opinion is on merge commits vs rebasing vs squashing. I've typed up this response so many times that I've decided to just put it in a gist so I can reference it whenever it comes up again.
I use merge, squash, rebase all situationally. I believe they all have their merits but their usage depends on the context. I think anyone who says any particular strategy is the right answer 100% of the time is wrong, but I think there is considerable acceptable leeway in when you use each. What follows is my personal and professional opinion:
# PATH: config/initializers/sidekiq_alive.rb | |
# AUTHOR: Andrei Makarov (github.com/amkisko) | |
# NOTE: now available as gem sidekiq_status_monitor (https://rubygems.org/gems/sidekiq_status_monitor) | |
class SidekiqAliveServer | |
attr_accessor :workers_size_threshold, | |
:process_set_size_threshold, | |
:queues_size_threshold, | |
:queue_latency_threshold, |
Known component/view patterns:
class Object::Proxy < SimpleDelegator | |
def initialize(object, **values) | |
super(object) | |
@values = values | |
end | |
def method_missing(name, ...) | |
@values.fetch(name) { super } | |
end | |
end |
This middleware does a few interesting things:
- Ensures a
url
shape in the zustand store, where we'll store URL information. - Assumes we will be storing our
url
state slice in the?state
search parameter after it has been stringified and base 64 encoded. - On creation, decodes stores state from the
?state
search parameter into theurl
slice of our store. - After each state update, updates the
?state
search parameter with the newurl
state slice. - Sets up an event listener that listens for
popstate
and re-decodes the state from the URL into our store.
Made this example to show how to use Next.js router for a 100% SPA (no JS server) app.
You use Next.js router like normally, but don't define getStaticProps
and such. Instead you do client-only fetching with swr
, react-query
, or similar methods.
You can generate HTML fallback for the page if there's something meaningful to show before you "know" the params. (Remember, HTML is static, so it can't respond to dynamic query. But it can be different per route.)
Don't like Next? Here's how to do the same in Gatsby.
# AUTHOR: Andrei Makarov (github.com/amkisko) | |
class ApplicationViewRecord < ApplicationRecord | |
self.abstract_class = true | |
def self.attribute_names | |
@attribute_names ||= attribute_types.keys | |
end | |
def self.load_schema! |
<div data-controller="address-form"> | |
<%= simple_form_for(address, url: address_path(address)) do |f| %> | |
<%= f.text_field :address, "data-address-form-target" => "address" %> | |
<%= f.hidden_field :address_lon, "data-address-form-target" => "addressLon" %> | |
<%= f.hidden_field :address_lat, "data-address-form-target" => "addressLat" %> | |
<div data-address-form-target="addressMapContainer" style="width: 500px; height: 500px; margin-left: -3.6rem;"></div> | |
<%= f.button :submit %> | |
<% end %> | |
</div> |