How render error 404 with custom layout with Phoenix? - phoenix-framework

By default, when an Ecto.NoResultsError occurs, the 404.html file is rendered without layout.
How I could define which layout must use this view?

Finally I do it:
defmodule AppWeb.ErrorView do
use Web, :view
def render("404.html", assigns) do
render(Web.ErrorView, "404_page.html",
layout: {Web.LayoutView, "empty.html"},
conn: assigns.conn
)
end
end

Related

How to get devcards working with shadow-cljs

My devcards used to work with Figwheel. However I can't get them to display with shadow-cljs.
Shadow emits this message:
shadow-cljs - HTTP server for :cards available at http://localhost:3450
The namespace cards.card-ui is just a series of requires.
I have a println message in cards.card-ui that is being displayed.
In shadow-cljs.edn I have two :builds. This is the second one:
:cards {:target :browser
:output-dir "resources/public/js/cards"
:asset-path "js/cards"
:modules {:main {:entries [cards.card-ui]}}
:compiler-options {:static-fns false}
:devtools {:http-root "resources/public"
:http-resource-root "resources/public"
:http-port 3450
:http-handler shadow.http.push-state/handle
:push-state/index "cards.html"
:preloads [devtools.preload
default-db-format.preload]}
:dev {:compiler-options {:devcards true}}
}
cards.html has a body tag that has a div tag that has id "app". I take the browser to http://localhost:3450/cards.html and just get a blank page. My best theory is that the cards.card-ui namespace is not being mounted at app.
Currently the only way to get an example Fulcro application that uses shadow-cljs rather than Figwheel is via the lein template. So at the command prompt:
lein new fulcro app shadow-cljs
Here app is any name you choose and shadow-cljs is an option. After studying the resultant application I realised that the namespace cards.card-ui should not just be a list of requires, but needs to have these lines as well:
(devcards.core/start-devcard-ui!)
(defn refresh []
(println "In cards.card-ui that starts the ui"))
The :cards build in shadow-cljs.edn becomes a bit simpler:
:cards {:target :browser
:output-dir "resources/public/js/cards"
:asset-path "js/cards"
:compiler-options {:devcards true}
:modules {:main
{:entries [cards.card-ui]}}
:devtools {:after-load cards.card-ui/refresh
:http-root "resources/public"
:http-port 3450}
}
Another thing I had wrong was the HTML (cards.html). Here is just the body tag of the markup:
<body>
<div id="app"></div>
<script src="js/cards/main.js"></script>
</body>
Some import pointers from the Devcards site: https://github.com/bhauman/devcards#usage-without-figwheel
The lein template project: https://github.com/fulcrologic/fulcro-lein-template

Multiple namespaces on Rails ActiveAdmin issues

I'm using active_admin and having issues setting up multiple namespaces.
Relevant files:
config/initializers/active_admin.rb:
config.load_paths = [File.join(Rails.root, "app", "active_admin")]
config.default_namespace = :superadmin
config.namespace :superadmin do |superadmin|
superadmin.site_title = "superadmin"
superadmin.authentication_method = :authenticate_superadmin_user!
end
config.namespace :admins do |admins|
admins.site_title = "admins"
admins.authentication_method = :authenticate_admin_user!
end
Then I have two subfolders, /admins and /superadmin:
app/active_admin/superadmin/dashboard:
ActiveAdmin.register_page "Dashboard" do
...
app/active_admin/superadmin/product_product.rb:
ActiveAdmin.register Product::Product, as: Product do
...
So far, so good.
Now, I can't seem to figure out how to add a dashboard for admins (or any other pages/models) without it blowing up.
If I go to localhost:3000/admins, I get the error uninitialized constant Admins::DashboardController.
I've tried adding:
app/active_admin/admins/dashboard.rb:
ActiveAdmin.register_page "Dashboard do
...
(which does nothing)
And namespaced:
app/active_admin/admins/dashboard.rb:
ActiveAdmin.register_page "Dashboard, namespace: "admins" do
...
which gives the error:
Invalid route name, already in use: 'admins_root'
You may have defined two routes with the same name using the `:as` option,
or you may be overriding a route already defined by a resource
with the same naming
I've also tried adding the subfolders in the load_paths:
config.load_paths = [
File.join(Rails.root, "app", "active_admin"),
File.join(Rails.root, "app", "active_admin", "admins"),
File.join(Rails.root, "app", "active_admin", "superadmin")
]
Please note that I've looked at the following, but none seem to actually work...
http://activeadmin.info/docs/1-general-configuration.html#namespaces
2 Namespaces of activeadmin
How to use multiple Active Admin instances for Complete Separate Models
EDIT:
I've also tried to remove config.default_namespace and the only thing that did was break localhost:3000/superadmin so that it has the error:
uninitialized constant Superadmin::DashboardController

Redirecting to #timecard results in 'no route matches [PATCH] "/timecards"

Can't figure out this routing problem: I redirect from my update controller action to the modified #timecard, and get the following error: No route matches [PATCH] "/timecards"
Why does rails try to redirect using PATCH and to timecards#index?
Is that not how I redirect to the recently edited #timecard?
In timecards_controller.rb:
def edit
#timecard = Timecard.find(params[:id])
end
def update
#timecard = Timecard.find(params[:id])
#timecard.update_attributes!(timecard_params)
redirect_to #timecard
end
Output of rake routes:
$ rake routes
Prefix Verb URI Pattern Controller#Action
timecard_timecard_entries GET /timecards/:timecard_id/timecard_entries(.:format) timecard_entries#index
POST /timecards/:timecard_id/timecard_entries(.:format) timecard_entries#create
new_timecard_timecard_entry GET /timecards/:timecard_id/timecard_entries/new(.:format) timecard_entries#new
edit_timecard_timecard_entry GET /timecards/:timecard_id/timecard_entries/:id/edit(.:format) timecard_entries#edit
timecard_timecard_entry GET /timecards/:timecard_id/timecard_entries/:id(.:format) timecard_entries#show
PATCH /timecards/:timecard_id/timecard_entries/:id(.:format) timecard_entries#update
PUT /timecards/:timecard_id/timecard_entries/:id(.:format) timecard_entries#update
DELETE /timecards/:timecard_id/timecard_entries/:id(.:format) timecard_entries#destroy
timecards GET /timecards(.:format) timecards#index
POST /timecards(.:format) timecards#create
new_timecard GET /timecards/new(.:format) timecards#new
edit_timecard GET /timecards/:id/edit(.:format) timecards#edit
timecard GET /timecards/:id(.:format) timecards#show
PATCH /timecards/:id(.:format) timecards#update
PUT /timecards/:id(.:format) timecards#update
DELETE /timecards/:id(.:format) timecards#destroy
root GET / timecards#index
When you call redirect_to you should specify a path.. not necessarily the object itself.
Try,
def update
#timecard = Timecard.find(params[:id])
#timecard.update_attributes!(timecard_params)
redirect_to timecard_path(#timecard)
end
The problem was naturally in the view. Thanks to #sircapsalot for pointing me to the log, which indicated that the incorrect route was indeed being called (from an incorrect link in the view).

Pass dynamic content to template in Middleman

I'm building a static site using Middleman that has a portfolio section of all the client's recent projects.
The portfolio section will display project thumbnail images in a 3 X 3 gallery fashion and, when clicked on, will open their co-responding html page inside a lightbox.
The layout for the pages inside the light box is the same so rather than markup each individual page, I thought there would be a way for Middleman handling the content served from a yaml data file (projects.yml) using [a link.
Here's what I've got in my config.rb file
###
# Page options, layouts, aliases and proxies
###
# A path which all have the same layout
with_layout :popup do
page "/projects/*"
end
# Proxy (fake) files
# page "/this-page-has-no-template.html", :proxy => "/template-file.html" do
# #which_fake_page = "Rendering a fake page with a variable"
# end
data.projects.details.each do |pd|
proxy "/projects/#{pd[:client_name]}.html", "/projects/template.html", locals: { project: pd }, ignore: true
end
Ok so after some digging I came across the two posts below which helped me under stand how dynamic pages work in middleman. (Unfortunately there's not a lot of doco and the Middleman example for Dynamic pages is really basic)
http://benfrain.com/understanding-middleman-the-static-site-generator-for-faster-prototyping/
http://forum.middlemanapp.com/discussion/134/best-way-to-use-yaml-same-html-but-parameter-driven-data-fixed/p1
My solution...
data/projects.yml (contains project details)
details:
- client: "Company X"
title: "Company X Event"
video_url: ""
logo:
- "logo_companyx.gif"
image_path: "/img/projects/companyx"
total_images: 10
content: "<p>Blah blah blah</p>"
responsibilities:
"<li>Something</li>
<li>Some task</li>"
config.rb:
data.projects.details.each do |pd|
proxy "/projects/#{pd[:client]}.html", "/projects/template.html", :layout => false, :locals => { :project => pd }, :ignore => true
end
The trick with the snippet above is passing the entire project data object to the template via a proxy using locals and setting the layout to false so it doesn't inherit the default site layout (as I - or the client rather - want to display these in a lightbox popup)
The last step in the process was to create /projects/template.html.erb (in the source folder), declaring the following at the top of the template
<% p = locals[:project] %>
This allowed me to output each property of the p object within template.html.erb.
eg:
<%= p[:title] %>
I hope this helps someone as it took me a few days of playing around and LOTS of searching online for example or hints.

rails routes using the do part for iteration

I have a very basic question, am looking at some rails code similar to following but not able to interpret it, what are the REST urls and corresponding actions inferred from this? Can someone please help understand as I did not find any examples of similar routes.
map.resources :myresources do |item|
item.resources :v, :controller => 'my_controller' do |v|
v.resource :abc
end
end
Thanks in advance!!
This is actually the old routing style.
Now you can just write the code this way:
resources :myresources do
resources :v, :controller => "my_controller" do
resource :abc
end
end
With this code you will get these routes:
myresource_v_abc POST /myresources/:myresource_id/v/:v_id/abc(.:format) abcs#create
new_myresource_v_abc GET /myresources/:myresource_id/v/:v_id/abc/new(.:format) abcs#new
edit_myresource_v_abc GET /myresources/:myresource_id/v/:v_id/abc/edit(.:format) abcs#edit
GET /myresources/:myresource_id/v/:v_id/abc(.:format) abcs#show
PUT /myresources/:myresource_id/v/:v_id/abc(.:format) abcs#update
DELETE /myresources/:myresource_id/v/:v_id/abc(.:format) abcs#destroy
myresource_v_index GET /myresources/:myresource_id/v(.:format) my_controller#index
POST /myresources/:myresource_id/v(.:format) my_controller#create
new_myresource_v GET /myresources/:myresource_id/v/new(.:format) my_controller#new
edit_myresource_v GET /myresources/:myresource_id/v/:id/edit(.:format) my_controller#edit
myresource_v GET /myresources/:myresource_id/v/:id(.:format) my_controller#show
PUT /myresources/:myresource_id/v/:id(.:format) my_controller#update
DELETE /myresources/:myresource_id/v/:id(.:format) my_controller#destroy
myresources GET /myresources(.:format) myresources#index
POST /myresources(.:format) myresources#create
new_myresource GET /myresources/new(.:format) myresources#new
edit_myresource GET /myresources/:id/edit(.:format) myresources#edit
myresource GET /myresources/:id(.:format) myresources#show
PUT /myresources/:id(.:format) myresources#update
DELETE /myresources/:id(.:format) myresources#destroy

Resources