Welcome/Home Page in Ruby on Rails - Best Practice

Welcome/home page in Ruby on Rails - best practice

The question is, is your home page just a landing page or will it be a group of pages? If it's just a landing page, you don't expect your users to hang around there for long except to go elsewhere. If it's a group of pages, or similar to an existing group, you can add an action to the controller it's most like.

What I've done for my current project is make a controller named Static, because I need 3 static pages. The home page is one of these, because there isn't anything to see or do except go elsewhere.

To map a default route, use the following in routes.rb:

# Place at the end of the routing!
map.root :controller => 'MyController', :action => :index

In my case this would be:

map.root :controller => 'static', :action => :index

If you wish to, you could create a controller just for this home page. I'd call it main, or something that you can remember which relates to the home page. From there you can get your data and your models and defer to the output view.

class MainController < ApplicationController
def index
@posts = Posts.find(:all, :limit => 10, :order => 'date_posted', :include => :user)
end
end

Assuming you have your model relationships defined correctly, the template to match it will be very simple.

Good luck, hope this helps.

Rails - Best practice to have completely two different designs

The application.html.erb file is considered a "layout" file, and the <%= yield %> is where each controller can insert the page content into your overall layout.

You can have two different versions of things by simply adding another file along side application.html.erb, named something like website.html.erb. Now, in any controller you have, you can simply add to the top, layout 'website', and all controller actions in that controller will use the website layout.

Using this, you can do some neat stuff:

  • Have two layouts, one for your application (the wallet app itself), and one for your website (the public pages that don't require a user account). Each layout can include different CSS and JS
  • Create a controller called something like static_pages_controller, which is meant for "static" pages (pages that do not largely change based on the user). For every page you want on the website, just add a controller action and an appropriate template. Tell this controller to use your website template like above.
  • Because your static pages are going through Rails, you can even check if a user is logged in, and change your content as-needed, so instead of saying "Log In", you can say "My Account"

You can read more about Layouts on the official documentation.

Rails best practice for having same form on multiple pages

By any chance is your Post model in a belongs_to relationship with each model who's controller you'll be using to render your form? Are you doing any special processing in the Post controller beyond Post.create(params[:post])?

If you answered yes to the first question and no to the second, you could get by with minimal mangling by adding accepts_nested_attributes_for to each of the controllers on which a user can create a post.

Regardless, Robertpostill is correct in that this is probably when to start looking at AJAX, to just replace the section of the page. The only problem is what to do if a user has javascript disabled. Personally I like to do design for the non-javascript case and add convenience methods.

As for thoughts on what you consider your two options,

1) I've used this method to store a shallow copy of an object in the flash hash. Preserving it across redirects. However this might not work for you given the variable nature of posts. As you can only send about 4K worth of data, and that includes other information in addition to your shallow copy.

2) See robertpostill's response

Best practice when developing an RoR application

Controllers should be RESTful, and should be appropriately named for the resources they manipulate.

The index action of your PostsController should have one purpose ... providing appropriate information relating to all of the posts to its view. The exact output of this could change within the view depending on whether you're logged in as an admin or not, but essentially the role of that action should be restricted to that function.

I would advise you to take a look at the CanCan gem and think about how you could use that to authenticate users, providing appropriate page content to admins and normal users alike.

Need explanation on best practices for sharing data amongst multiple methods of a controller

The first thing you need to understand is that each each HTTP request will be routed to a precise Controller#action.

Rails will instantiate a new Controller object for each request, and will then destroy these instances as soon as the requests they are serving have been completed.

This means that two requests from the same client, even if concurrent or subsequent, will be be handled by two different instances of the Controller.

Also, if you decide to halt the execution of an action by calling redirect_to another_path, that will also be a different HTTP request, as rails will return the browser a 302 response with the new path as the destination of the redirection.

To answer your more practical question, you need to:

  1. store somewhere the state of your application (the file, the date and time of the upload, the user who uploaded it, etc)
  2. ensure that the index action has the means to retrieve that data.

On point 1, you can use the cookies, you can save that data in the DB and associate it to the user, etc.

On point 2, you can either retrieve that data using the user reference, or you can pass an explicit reference to the path helper, for example:

uploads_path
# => /uploads

uploads_path(custom_parameter: "ninja-turtles", upload_id: 1337)
# => /uploads?custom_parameter=ninja-turtles&upload_id=1337

done that, you'll have access to those parameters in the new action:

params[:upload_id]
# => "1337"

Just be careful, because passing sensitive data as part of the URL string means that anyone can try to supply manually crafted parameters.


If you don't want to use different actions, on the other hand, you can just render the index.html.erb template at the end of the POST upload action.

In Rails, actions will default to render the templates of the same name, but of course you can customize that.

Static pages in Rails?

There are a variety of approaches you can take (they're not all good approaches).

1 - public directory

If it's truly static, you can put it in the public directory. Things in the public directory will be served immediately, without going through the Rails stack.

Advantages:

  • Because it doesn't have to waste time going through the Rails stack, the client will receive a faster response.

Disadvantages:

  • You won't be able to use your sites layout. Or view helpers like link_to.
  • Instead of your views being in one place (app/views), now they're in two places (app/views and public). This can be confusing.

Thoughts: I feel pretty strongly that the disadvantages outweigh the advantages here. If you're looking to make a minor improvement in speed at the expense of readability and programmer happiness, why use Rails in the first place?

2 - Place in app/views and render directly from the Router

It is possible to render views from the router. However, it definitely isn't The Rails Way.

From the official RailsGuide on routing:

1 The Purpose of the Rails Router

The Rails router recognizes URLs and dispatches them to a controller's action.

Architecturally, there isn't anything inherently wrong with having a router map directly to a view. Many other frameworks do just that. However, Rails does not do that, and deviating from an established convention is likely to confuse other developers.



like should I create a controller or not?

Unless you want to take one of the approaches mentioned above - yes, you should create a controller.

The question then becomes what to name the controller. This answer outlines some options. I'll list them here with some thoughts. I'll also add three other options.



3 - Use ApplicationController

# routes.rb
get "/about" to: "application#about"

# application_controller.rb
class ApplicationController < ActionController::Base
def about
render "/about"
end
end

# app/views/about.html.erb

The advantage here is that you don't introduce overhead/bloat by creating a new controller and folder. The disadvantage is that it's not The Rails Way. Every controller you create inherits from ApplicationController. ApplicationController is typically used to house functionality that you want to share between all other controllers. See this example from the Action Controller Overview Rails Guide:

class ApplicationController < ActionController::Base
before_action :require_login

private

def require_login
unless logged_in?
flash[:error] = "You must be logged in to access this section"
redirect_to new_login_url # halts request cycle
end
end
end

4 - StaticController or StaticPagesController

Michael Hartl's popular Ruby on Rails Tutorial uses a StaticPagesController. I agree with the source I got this from in that I don't like this approach because the pages often aren't actually static.

Also, there is a possibility of confusion - why did we put other static views in separate controllers? Shouldn't static views be rendered from the StaticPagesController? I don't think the possibility of confusion is too high, but still wanted to note it.

Also note Hartl's footnote:

Our method for making static pages is probably the simplest, but it’s not the only way. The optimal method really depends on your needs; if you expect a large number of static pages, using a Static Pages controller can get quite cumbersome, but in our sample app we’ll only need a few. If you do need a lot of static pages, take a look at the high_voltage gem. ↑

5 - PagesController

The official Ruby on Rails routing guide uses PagesController. I think this approach is fine, but it isn't descriptive at all. Everything is a page. What distinguishes these pages from the other pages?

6 - UncategorizedPagesController

I would call the controller UncategorizedPagesController, because that's exactly what they are - uncategorized pages. Yes, it's a little more cumbersome to type and read. I prefer the advantage of clarity over conciseness, but I could understand the choice to be more concise and go with PagesController, or something else.

7 - High Voltage gem

With High Voltage, you don't have to do the tedious work of writing out routes and empty controller actions:

# routes.rb
root 'pages#home'
get '/about', to: 'pages#about'
get '/contact', to: 'pages#contact'
get '/help', to: 'pages#help'
get '/terms-of-service', to: 'pages#terms_of_service'
get '/landing-page', to: 'pages#landing_page'
...

# pages_controller.rb

def PagesController < ApplicationController
def home
end

def about
end

def contact
end

def help
end

def terms_of_service
end

def landing_page
end

...
end

You just add your pages to app/views/pages and link to them: <%= link_to 'About', page_path('about') %>.

Rails Separate Controller for Page with many Models? What is best?

You're right that this is more a RESTful dilemma and not related to any specific framework. It depends on the role of the Parent and Child Models and whether the dashboard 'exposes' any other additional resources. For the sake of simplicity I'm going the pretend the parent model is an Author and the child model is a Book.

If the dashboard only contains a collection of children related to a parent model you could consider using Nested Resources. E.g URLs similar to /authors/{author_id}/books (and alias to /dashboard if required):

# routes.rb
resources :authors do
resources :books
end

The logic then belongs in the BooksController:

class BooksController < ApplicationController
def index
if params[:author_id]
@author = Author.find(params[:author_id])
@books = @author.books

return render '/books/author_index'
else
# Code for simple top level RESTful resource. E.g '/books'
# ...
@books = Book.all

return render 'index'
end
end
end

However if your dashboard is more broad and touches multiple domains, you could consider the dashboard as a resource in itself (e.g it's own DashboardController) as described in this answer.



Related Topics



Leave a reply



Submit