The goal: our ruby on rails app dynamically builds routes from information in a table, so when someone edits information in that table, we need a way to refresh the routes on both servers automatically. We have a folder in our views containing templates. A route to that view is automatically created based on data in a table:
routes.rb
namespace :templates do
templates = PdfTemplate.all.pluck(:shortcode)
resources :pdfs, only: templates do
templates.each do |template|
get template.to_s, on: :collection
end
end
end
We want the routes to be updated automatically in the event someone changes the shortcode of a template in the database.
My attempt: Previously, I tried adding a call back on the model for after_save
if attribute_changed?
to do Rails.application.reload_routes!
, which refreshes the routes just like we need. However, because our app has 2 servers, it only updates the routes on one server, not both, causing issues from that discrepancy.
The real question (finally): what's the best way to refresh the routes on both servers of our app? We're using Ruby v2.1.2, Rails v4.1.6, and mysql.
spickermann has it right (especially the XY Problem comment). I just wanted to mention you could also do:
namespace :templates do
scope :pdfs do
get '*shortcode', to: 'pdfs#show', as: :pdf
end
end
Which gives you:
templates_pdf GET /templates/pdfs/*shortcode(.:format) templates/pdfs#show
'*shortcode'
is a wildcard matcher. So, if you have a URL like:
localhost:3000/templates/pdfs/a-cool-template
It will route to templates/pdfs#show
with a params[:shortcode] == 'a-cool-template'
.
Then, your Templates::PdfsController
might look something like:
class Templates::PdfsController < ApplicationController
def show
begin
render params[:shortcode]
rescue MissingTemplateError
# do something here
end
end
end
If app/views/templates/pdfs/a-cool-template.html.erb
exists, it will be rendered. If it doesn't, then you catch the MissingTemplate error and respond accordingly. (BTW, I forget what the actual name of the MissingTemplate error is, so what I have there is probably not correct.)
If you have multiple template types, you could do:
namespace :templates do
[:pdfs, :html].each do |template_type|
scope template_type do
get '*shortcode', to: "#{template_type}#show", as: template_type
end
end
end
Which gives you:
templates_pdfs GET /templates/pdfs/*shortcode(.:format) templates/pdfs#show
templates_html GET /templates/html/*shortcode(.:format) templates/html#show
Why do not you just allow all routes and handle 404 in the controller?
I would change the config/routes.rb
to something like this:
get 'templates/pdfs/:shortcode', to: 'pfds#routing', via: :get
And add a method like this to the PdfsController
:
def routing
pfd_template = PdfTemplate.find_by!(shortcode: params[:shortcode])
# code needed to handle the shortcode
end
There are going to be multiple ways to achieve this, but what I would do is simply add a trigger to your mysql database to call an API endpoint which in turn updates the routes.
An example of using mysql triggers to make http calls: can be found here
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.