Best practices for static pages in a rails app

I am developing an app in ruby ​​on rails for a local business. The pages are "static" but are modified by the backend CMS I create for them. Is there a best practice for creating a controller for static pages? Right now I have a site controller with all static routes like this.

routes.rb

get "site/home"
get "site/about_us"
get "site/faq"
get "site/discounts"
get "site/services"
get "site/contact_us"
get "site/admin"
get "site/posts"

      

or I'd be better off creating member routes for the site controller like this without the crud, because the "site" doesn't need CRUD.

resources :sites, :except => [:index, :new, :create, :update, :destroy]
member do
  get :home
  get :about_us
  get :faq
  get :discounts
  get :services
  get :contact_us
  get :admin
  get :posts
end

      

Or is there a best practice / better way? Any answers would be appreciated. Thanks to

+3


source to share


3 answers


If the list of static pages won't grow, you can keep the list, but if you need a dynamic list like site / any_new_url, keep the routes as

get 'site/:cms_page' => 'cms#show' # all requests matching site/any_page will go CmsController, show method

      

This will help reduce the retention of routes from bloating, but the downside is that you don't know that all routes are valid. Your example code could be



def show
  @page_data = Page.find_by_page(:params[:cms_page])
end

      

show.html.erb

<%= @page_data.html_safe %>

      

+5


source


I don't know if I consider this to be best practice or an abomination, but here is what I came up with while solving the same problem.

My reasoning is that the site provided some functionality (which doesn't really matter to this discussion) + a bunch of information about the organization itself (about us, contacts, FAQ, home page, whatever). Since all of this data was really related to the organization, the Organization model seemed reasonable with each of these things as attributes. Here's the model:

class Organisation < ActiveRecord::Base

  ...validations stuff...

  def self.attrs_regex
    Regexp.new(self.attrs.join("|"))
  end

  def self.attrs
    self.column_names.reject{|name| name =~ /id|created_at|updated_at/}
  end

end

      

Then I use the attrs class method to generate the column-based routes. This is in my .rb routes:

Organisation.attrs.each do |attr|
  get "#{attr}" => "organisation##{attr}", :as => attr.to_sym
  get "#{attr}/edit" => "organisation#edit", :as => "#{attr}_edit".to_sym, :defaults => { :attribute => attr }
  post "#{attr}" => "organisation#update", :as => :organisation_update, :defaults => { :attribute => attr}, :constraints => Organisation.attrs_regex
end

      

The controller is a little weird and I'm not crazy about the code here, but it doesn't matter here. I need to make sure the attribute is set and available for views, so I can get it right, so I set it in my app controller:

class ApplicationController < ActionController::Base
  protect_from_forgery
  before_filter :set_attribute

  def set_attribute
    @attribute = action_name.parameterize
  end

end

      



For the organization controller, I just set the @organisation variable as the first and only line in the database in the before_filter, and then lets Rails do the usual magic of calling a method, failing, and rendering the same name.The edit action just uses one view file to edit all different attributes:

class OrganisationController < ApplicationController


  before_filter :set_organisation

  def edit
    authorize! :edit, @organisation
    @attribute = params[:attribute].parameterize
  end

  def update
    authorize! :update, @organisation
    @attribute = params[:attribute]
    respond_to do |format|
      if @organisation.update_attributes(params[:organisation])
        format.html do 
          redirect_to "/#{@attribute}", notice: t('successful_update')
        end
        format.json { head :ok }
      else
        format.html { render action: "edit" }
      end
    end
  end

  private

  def set_organisation
    @organisation = Organisation.first
  end

end

      

So this is where I ended up. Like you, I ended up on SO to bring in a ton of genius here, but ended up with disappointing results . If there is something better, I still hope to find it.

What I like about what I have done is that the routes are automatically generated based on the organization table structure.

What I don't like about what I have done is that the routes are automatically generated based on the organization table structure.

I know I will pay for this design decision when I have to tinker with i18n routing, and there are probably a thousand other reasons that this is a bad idea that I haven't discovered yet, but I have a happy client at this point.

At the end of the day, that doesn't mean you should be doing this, but I hope to give you more than I do so that you can advance your thinking on this and hopefully end up a little closer to this best practice.

+1


source


If you are going to create a CMS that probably connects to a database and allows your client to change the text on the pages of their site, then I would not recommend using static pages. In Rails terms, a static page will link to create html files in the / views / pages directory. If you go this route, you are going beyond how Rails was designed.

I believe you want to create tables in the database that match and store data for your posts, etc. You can pull information into the controller from the model it matches and then the user sees the data display. You can create a layout for these pages and then create controllers for each page you add.

As far as routes are concerned, I would recommend using the following:

map.resource :controller_name

      

you will then add code that displays the information from the CMS in the appropriate show and view manager action for each page.

0


source







All Articles