how to set custom controller for page_layout

454 Views Asked by At

I'm trying to set my own controller for a page_layout, because I want to override the actions to get other models into the view.

Edit: frontend rendering works now. Only backend is buggy

From the docs, i did:

# config/alchemy/page_layouts.yml
- name: index
  unique: true
  elements: [article, other_element]
  autogenerate: [article]
  controller: 'my_custom'
  action: 'index'

and created a app/controllers/my_custom_controller.rb:

# app/controllers/my_custom_controller.rb
class MyCustomController < Alchemy::PagesController
  def index
    @some_values = Value.all
  end
end

my routes.rb lookes like this:

Rails.application.routes.draw do

  root 'my_custom#index'

  devise_for :users,
             path_names: { sign_in: 'login', sign_out: 'logout' },
             controllers: { sessions: 'users/sessions', passwords: 'users/passwords' }

  mount Alchemy::Engine => '/'

The root-page has the page_type index in alchemy.

And when i go to localhost:3000 I get what I want

But in the alchemy backend, when editing the page, i get an error when rendering:

NoMethodError in Alchemy::Admin::Pages#show
Showing app/views/alchemy/elements/_some_element_view.html.erb where line #2 raised:

undefined method `each' for nil:NilClass
Extracted source (around line #2):
<div class="row">
  <% for @value in @some_values %>
      <%= render 'value/basic_view' %>
    <% end %>
</div>

probably, because the @some_values are not initialized, what would mean, that my controller wasn't used to render this. Am I doing something wrong?

Edit2: Maybe I'm on the complete wrong track. I want to have an Alchemy-Element, that renders stuff from the database (custom models). What I did is, creating an element, that renders the @some_values. And by specifing my custom controller on every page-type where this element can be placed on, I allow my editors to place those @some_values where they want.

1

There are 1 best solutions below

2
tvdeyen On BEST ANSWER

It looks like this is not the right approach for what you want. Custom controllers for page layouts was introduced for routing reasons. So that editors can manage the navigation for custom controllers. They are not meant for decorating the default element and page rendering.

What you probably want is a on_page_layout callback: http://www.rubydoc.info/github/AlchemyCMS/alchemy_cms/Alchemy/OnPageLayout

In your case:

class ApplicationController < ActionController::Base
  extend Alchemy::OnPageLayout

  on_page_layout :foo do
    @some_values = Value.all
  end
end

Or, even easier, load the values inside the the element view. A little PHPish, but also ok.

EDIT:

From a performance perspective using low level rails cache in your controller is a good practice:

...
on_page_layout :foo do
  @some_values = Rails.cache.fetch('some/cache/key', expires_in: 10.minutes) do
    Value.all
  end
end
...