Rails 4 Views - Best Practices - ruby-on-rails

I have two controllers, UsersController and TransactionsController and I'm wondering what the best practices is for displaying data from both controllers on one view. Should I create partials under each corresponding views directory and then stitch them together in a separate view or do I create one view under layouts? Am I way off?
EDIT:
In my Views folder:
devise
(devise default views are in here)
layouts
_header.html.erb
application.html.erb
transactions
_form.html.erb
index.html.erb
delete.html.erb
edit.html.erb
new.html.erb
users
index.html.erb
I want to show both all users in one table and their transactions in another on the root page.

If transactions belong to user, you should be able to access transaction data on the user page by default (if models&migrations are set up correctly). If your users index.html.erb will be your root page, that should solve your problem.

If you are trying to show this data in an administration page for example then your code should go like this
Controllers:
admin_controller.rb -> with action users_transactions
views/admin
users_transactions.html.erb -> loop on users showing the partial of user
views/transcations
_user_transactions.html.erb
views/users
_user.html.erb -> here you will show how a single user will show including the partial of his transactions.

So I guess it all depends on 'what' you want to display and 'how'.
Leave the views/layouts Dir for what it was created, storing layouts. Generally cross-view partials are kept in the views/shared Dir, which stores partials that could be rendered from another directories. in your case form transactions/* & users/*.
Plan wisely before adding a file there... maybe you don't really need it ;)

Related

What is the proper workflow for storing data without multiple instances of database models?

I'm relatively new to web development. I am using ruby on rails.
If I had a website with blog posts, I would have a Post model inside my DB and would CRUD instances of it. What if I had an "about" page (where users can read about the blog) and wanted to edit a block of text on the "about" page? How would I go about updating the text displayed on that page?
It doesn't sound like it would make sense to store the data in a DB model as I would only have one instance of such model (since there is only a single "about" page).
What would be the appropriate workflow for storing and editing this data if I will only have one instance of it?
Static pages do not have any dynamic data - thus can be just plain HTML files or .html.erb in basic rails views.
All you need to do is create something like:
Have a route to yourpage.com/about.html inside your routes.rb file
get "/about", to: "static_pages#readme"
Have a controller to serve this route
class StaticPagesController < ApplicationController
def about; end
end
Notice there's no dynamic data on the about page so we do not have to set any variables inside a controller. (like you would set #posts in your PostsController)
Have a view template with the data you need to be displayed on /about page
app/views/static_pages/about.html.erb
PS. If you'd like to bypass rails all the way you can drop about.html inside public/ folder and check yourpage.com/about or localhost:3000/about.html in dev environment. (Look for 404.html page for reference), but I'd keep with the rails way.

Render a form in a modal(bootstrap) and make it available on another controller's view

It's been a while since I've used Rails and I think I've gotten a little rusty. Is there a way to do this?
I'm trying to make a messaging feature that allows one user type to message another. I want the button to display on the User index page and the user show page. When the button is clicked a modal will popup with a form contained therein.
Currently I've made a Message model with three columns: user_type1_id, user_type2_id and message_body.
Should I make a distinct controller for this new model? Or should I put the logic in the controller of user_type1 (the usertype that will be messaged)?
Any other suggestions would be welcome.
Controllers are there primarily to get data from the database and get it ready for the views. So if you have user#index and user#show pages, then you should use the UsersController for all the logic associated with those views, even though it uses other modals. It really is the "Rails Way". If, however, you were to create a message#index page, then you should create the associated MessagesController.
Also, there is nothing wrong with creating a partial and sticking in the messages view directory (the filename would be, say, messages/_form.html.erb). Then, whenever you needed that form (throughout the entire site), all you would need to do was type:
<%= render 'messages/form' %>

Rendering different parts of a page from different actions from different controllers

I've got an index page where I've decided to render both Usernames, Posts and other informative sources.
Since Devise takes care of the user creations and login sessions-managing I am aware of needing to have multiple controllers.
PostsController, DashboardController and RandomController. The plan is to make them be rendered on different parts of the page, with different sizes and on different places.
Let's say I've got Post.find(:all => :order => "created_at DESC") in the PostsController. I want to render that someplace on the page.
I want to render Usernames right under the according Post which belongs_to them, and I want to render some still "Random" Controller action which will post news on some random place on the page.
So a recap:
The PostsController finds and renders some part of the index page, and the DeviseControllers I guess renders the username belonging to the according one, and the Random Controller renders some random thing from news or something on the middle of the page. Amongst all of them all of this is happening on another controller called DashBoard.
So all these controller actions are supposed to be rendered on a own DashBoard controller index view.
Any tips, or good ideas on how to accomplish this. I know about partial rendering, but I don't know how to achieve that.
It seems we're talking about a view rendered by Dashboard#index. So all you need to do is define all the info on the page as instance variables under the index action.
Probably the bit of info that's missing for you is that controllers are free to use data from any of your models (and even other classes that don't inherit from ActiveRecord::Base).
For instance, in Dashboard#index, you can have:
#posts = Post.order("created_at DESC").all
Which is referring to a different model than the Dashboard model (assuming one exists).

Nested RESTful routes in Rails: how should I organize my views?

Lets say you have an Invoice resource, and each Invoice has nested InvoiceLine resources, i.e. a very common nested resource pattern.
Now, where should one put the view for showing each individual invoice line as a row within the invoice? Should invoice lines be rendered as a partial under invoices/_line.html.erb, or should they get their own full-fledged view under invoices_lines/show.html.erb? Normally the former would be the obvious choice, but when you add AJAX functionality (for adding and editing lines in the invoice show view), things get complicated.
I find myself really struggling with this on a regular basis, and I'm not really sure of the right way to deal with it.
Here's what I'm thinking:
A RESTful route for this will likely look something like this:
map.resoures :invoices do |invoice|
invoice.resources :lines, :controller => :invoice_lines
end
The standard folder structure for the views is:
app/
views/
invoices/
invoice_lines/
Now, when rendering the entire invoice with all of its lines, my inclination would be to make each line into a _line.html.erb partial under invoices/. But then when I want to add some AJAX functionality for adding and editing lines, the PUTs and POSTs are routed to the invoice lines controller, so shouldn't the line rows be rendered by a standard show.html.erb view under invoice_lines.erb?
So should my views look like this:
app/
views/
invoices/
index.html.erb
show.html.erb
_line.html.erb
invoice_lines/
Or like this:
app/
views/
invoices/
index.html.erb
show.html.erb
invoice_lines/
index.html.erb
show.html.erb
I'm stuck between having the InvoiceLinesController render its response to AJAX requests using the partial in invoices/_line.html.erb, or I can put the line row template code in invoice_lines/show.html.erb, and have invoices/show.html.erb render the individual lines as a component or AJAX request to InvoiceLinesController#index.
Neither alternative feels right. Any suggestions on the best practice here?
It feels as if invoice lines controller should have it's own set of views when rendered in the context of the invoice, but Rails doesn't really have an obvious provision for "contextualized" views.
What about to put a partial _line.html.erb into the invoice_lines folder and then use this partial in the invoices_lines/show.html.erb template and the invoices/show.html.erb.
That's how I did it in similar situations.
This way all invoice specific view code is in the invoice folder and all invoice_line code is in the invoice_line folder.
You are DRY: you can use Ajax calls to the invoice_line controller or render the whole thing by displaying invoice/show.html.erb.
invoice_items would be rendered both times through the same partial in invoice_lines/_line.html.erb
I hope this makes sense and is sort of an answer to your question. I'm not yet too experienced with Rails so I can't tell if this is "best practice"

Two controllers for one shared view in Ruby on Rails

I have two controllers for two respective models, by example, photos and categories. index and show methods are very similar in each controller, and the views are identical. What is the best method for share the view by the two models?
I've though two options:
Use a helper. In the helper will put the code for the view, and will call the helper from each view (photos/views and categories/views)
Use a partial in each views. I think it's a more clean solution, but I see huge DRY's in my mind when going to code this solution.
So, I have two controllers from two models, each one at and exposes a #photo object (photos controller with all the photos, and categories controller with just the selected categorie's photos) and I need one view to show both.
I'm looking for an elegant solution for this, complaining REST and DRY principes. Any idea?
Thanks in advance.
I have a similar situation with one of my projects. All the delete views for most controllers are styled the same way, display the same confirmation boxes, and simply renders a predictable display of whatever object is being deleted.
The solution was quite simple and elegant in my opinion. Simply put, what we (the developers) did was create a new directory in app/views called shared and put shared views in there. These could be full template files or just partials.
I would suggest using a shared template (in neither categories nor photos view directories, but rather in the shared directory) and rendering it manually from the view.
e.g. have a method as such in both controllers and a file app/views/shared/photo.html.erb:
def show
#photo = Photo.first # ... or whatever here
render :template => 'shared/photo'
end
This should successfully render the shared template. It is the DRYest route and doesn't have the feeling of pollution you get when using a more-or-less empty view in each controller's view directory just to include a shared partial, as I understand your question is suggesting.
About the first answer:
If the partial must be rendered from a view:
<%= render :partial => "shared/photo" %>
and the partial must be in app/views/shared/_photo.html.erb
I'd use an helper because they are shared among views. For the HTML part, I'd use partials so it would be a mix of both ways.
This looks like a good use case for the Cells gem.
#bjeanes If all your delete views are the same, you can create views/default/delete.html.erb and all the delete actions will use it.
That's what i'm doing: Most of my views are on default, and i create specific ones only when needed
Update: Ok, this post is from 2009, anyway, i will keep my comment here in case someone gets here from Google like i did.

Resources