I am using Rails 3. Consider the following code listed at bottom.
1) Should links to other actions be done via href (href="/foo/bar") or via #id (id="#foobar_div")? In some document I read online. Providing an actual link to the href attribute tells the iPhone to execute an AJAX call.
If I provide an div#id instead, then it loads the page without ajax (the same way browsers do this). However, providing div#id's means that all content has to be declared a single page.
Whats the right way for calling other pages on the server?
2) Is there anything wrong with the code structure below? i.e. can I style my own span elements like this?
3) The demo pages indicate that all content should be in one page. However, Ryan Bates from railscast.com has an episode about jqtouch and his pages are separate. which is the proper way?
<ul>
<% #songs.each do |song| %>
<li class="arrow">
<%= link_to(song_path(song)) do %>
<%= image_tag(song.user.profile_image, :alt => 'profile image', :style => 'float:left;') %>
<span class="title"><%= song.title %></span>
<span class="artist">by <%= song.user.first_name %></span>
<span class="likes"><%= song.likes.count %> loves</span>
<% end %>
</li>
<% end %>
</ul>
For your first and third questions (which to me are the asking the same thing), it depends on the project you're working on.
If you're providing static contents, you can just load all the pages in one hit, hence using "id=#foobar_div", as long as there are not that many pages (as you don't want the users to hold the phone and look stupid in front of their friends waiting 30 minutes for your site to load).
If you're providing dynamic contents or there are too many pages for your site, you may want to use the AJAX approach, at least for some pages.
At the bottom line, you want to load as many static pages as possible while still keeping your site responsive.
For question 2, I'm not quite sure I got what you're asking. I can't see anything obviously wrong, but again, I'm not a rail programmer.
Related
Reviewing some starter courses, I see that the terms are used separately, but I think I only understand layout. To my knowledge the layout is a temporary portion of code (such as a right navigation section, a div containing an ad, or something similar), and a partial is a partial template, but what is a template, and how does it differ from a layout?
Can you give a definition of all three with relations to each other if possible? (ie a template is .... and there are two kinds, partials and layouts.... layouts are specific types of templates or whatever the answer is)
Please correct my assumption if needed...
In Railscasts 294 using pjax, layouts are explicitly differentiated by the random number generator, and this is why I got lost.
I am trying to make a single page accessed by App/Verb/noun, where i can either "capture" or "display" "photos", "videos", "images", etc...(app/captures/photos or app/captures/videos or app/displays/photos etc) and am trying to make just one div change based on when I "capture" different things.... and I am getting lost in the verbiage, or I get really close but am not really understanding what im doing.
I know this is an old question, but I've wondered the same. In the guides, there is no clear explanation of the difference between layouts and views, nor is there a clear explanation of the relationships. To add to the confusion, the term 'template' is often used for both. As someone that was programming Smalltalk in the 90s (but is new to Rails) I deeply understand MVC and understand some of the many ways that it an be implemented -- so my confusion wasn't with that part. There's just a missing piece of context about views, layouts, and templates and how they relate to each other.
Here's how I came to understand it:
Start with a simplistic understanding and example so that the relationship and role of each part is clear:
a view is 'stuff to be displayed' for a particular controller to respond to an action (which puts it into a particular state). A view is a snapshot of your model at in a particular state, for a particular action (reason/context). It's about information and state, not necessarily about 'looking good'.
a layout has specific information on how something will be displayed. It may have markup (CSS, HTML, etc.) that provides instructions on how something will be organized (this part up here, that part over there, those go at the bottom, these float at the top; that is navigation information, this is H1, that's H3, this is a definition..) and how it will look (left, right, up, down, red, green, emphasized, flashing, hidden, big, tiny, Helvetica, etc.)
Think "Layout and Looking Good"
Say you have a Contract model and controller, and you have a file that defines the view: view/contracts/show.htm.erb:
<% content_for :full_identification do %>
<p><%= contract.display_name %> <%=contract.full_id_number %> </p>
<% end %>
<% content_for :summary do %>
<p> This is the summary for <%= contract.simple_name %>. You hire us. We give you coolness. You pay us.</p>
<% end %>
<% content_for :client_info do %>
<div class="client-info">
<p><span class="contract-title">Client: <%= contract.client_name%></span></p>
<p>Address: <%= contract.client_address%></p>
<p>Phone: <%= contract.client_phone %> </p>
... more info about the client....
</div>
<% end %>
<% content_for :scope_of_work_statement do %>
<p class="scope-of-work-statement"><%= contract.scope_of_work%>:</p>
<% end %>
Your layout file would have more details about the HTML (assuming HTML output) and specifics about how you want things to look. Maybe you have a controller and view that is specific for what (and how) the client sees that contract. You have a layout file for that specific controller and it looks like this:
layouts/contracts/contracts_clients_view.htm.erb
<div class="tab-pane fade in" >
<div class="span7 highlight >
<%= yield :full_identification %>
<div class="no-breaks reflow" >
<%= yield :summary%>
</div>
</div>
<div class="span5 scope-of-work-statement">
<h3>Scope of Work Statement</h3>
<%= yield :scope_of_work_statement %>
</div>
</div>
</div>
*[This is a totally contrived example so that I can make the relationship between view and layout clear. Obviously things would be modeled and expressed differently in the real world. ]*
The view provides input (the content pieces) to the layout.
Views are for controller actions and are named accordingly. (Ex: show, edit, index, etc.)
Layouts are named for the controller used to render them. (Ex: application -- for the ApplicationController, contract -- for a ContractController, contract_customers_view -- for a ContractCustomersViewController)
Where it starts to get tangled is that a view can also have layout information in it. Sometimes there is only the view file (no layout file). And either one can be written in a template language (like ERb or HAML) and thus they can both referred to as a template.
A partial is really just what it says: it's just a piece that can be used (and hopefully re-used). You can take part of a view or layout and re-factor it so that you can re-use it -- now it's a partial. Common uses of partials include the head section, navigation sections (including header, footer, etc.), places where you can re-factor for reusability, and improving coding style and readability by using them for semantic and logical sections. (That's why people liken them to a subroutine.)
Another place where you can get some context about views and layouts and how they're different is in the steps (flow) that ActionView goes through to actually produce output -- to render something using all of these pieces. It is important to understand when a layout is (or isn't) created, for example, so you understand which variables and parameters are or aren't available to you at a particular time.
(I'm working with Rails 4, btw.)
Given all of that, now imagine that all of your layout information is in your views, and that your views are written in a template language (ERb, HAML, etc.), and that you've used partials to make everything sing better. You may not have any layout files beyond one main one for your application that has a big yield in it where the real content (generated by your controllers & models) goes.
Hope this helps someone else get a handle on views and layouts. (And I suppose I should suggest putting something like this into the guides.)
From http://www.tutorialspoint.com/ruby-on-rails/rails-layouts.htm : A layout defines the surroundings of an HTML page. It's the place to define common look and feel of your final output. Layout files reside in app/views/layouts.
Template is a general term for the view files. A view template - residing in app/views/ folder - would be rendered within a layout.
Best resource to understanding how Rails views work is the Ruby on Rails Guides page on Layouts and Rendering : http://guides.rubyonrails.org/layouts_and_rendering.html
What is a layout?
(a) Let's start with the problem we are trying to solve
You might have 1000s of different "pages"/views on your rails app. All 1000 of those pages/views share the same headers, and footer. Now imagine you had to change the footer for your site: you would have to make that change in 1000 pages! What a nightmare: this is not efficient.
You can extract the headers and footers and place it in a layout.html.erb file which can be used by all 1000 pages. In that way: 1 change in one place can propagate to all 1000 of your views/pages. So if you want to change your header/footer you only need to make that change in ONE place, and that will be applied to all views that utilise that relevant template.
# example of a layout
# app/views/layouts/application.html.erb
<!DOCTYPE html>
<-- THIS IS SIMPLIFIED - DO NOT COPY this example -->
<html>
<div>
<%= yield %> <-- Notice the yield statement -->
</div>
</html>
# example of a view:
# users#show.html.erb
<-- This uses the application.html.erb layout -->
<-- Notice how I don't have to create a html tag - because this has already been created in the application.html.erb -->
<div class="container">
<h1> About <%= #user.full_name %> </h1>
<br>
<p>
<b> Name: </b> <%= #user.full_name %>
</p>
<p>
<b> Organisation: </b> <%= #organisation.name %>
</p>
<p>
<b> Email: </b> <%= #user.email %>
</p>
</div>
The rails app firstly renders the layout, and then yeilds to the specific views that you want to display. Now you can change the layout and have it propogate through to all your subsequent "views" which utilise the layout.
I would like to have a right side bar with content changes for each page.
For example, when I am in Friends page, the side bar should display New Friends.
When I am in Account page, the side bar should display Recent Activities.
How should I go about this to respect Rails design patterns? I heard about Cells gem, but I am not sure if I use it.
here is one way, in your layout add a named yield section
<div id="main-content">
<%= yield %>
</div>
<div id="side-content">
<%= yield(:side_bar) %>
</div>
Then in your views put content into the named yield using content_for
# friends view ....
<% content_for(:side_bar) do %>
<%= render :partial => "shared/new_friends" %>
<% end %>
# account view ....
<% content_for(:side_bar) do %>
<%= render :partial => "shared/recent_activity" %>
<% end %>
this requires you to be explicit about what content appears in the side bar for every view,
maybe having it do it dynamically is better? probably depends on the specific situation and your preference
see also - http://guides.rubyonrails.org/layouts_and_rendering.html#understanding-yield
I came by this question in a moment of a big design change in our views. After thinking about the sidebar problem a bit, I realized that there's no best solution (as always). There are better solutions for each case.
I'll compare 3 solutions here:
using content_for(:sidebar) and yield(:sidebar)
using the partials approach
using the Cells gem
1. Using content_for(:sidebar) and yield(:sidebar)
This is good for cases when each link (each controller action) you access renders a different sidebar. In this case, each view you access will have the content_for(:sidebar) part.
If your sidebar view depends only on the state of some variable in the session, for example, the sidebar should not be rendered for every link you access.
Then you should use a good caching system like turbolinks, to avoid rendering many times the same thing, or use something like the Cells gem with a javascript to render only the main part of the layout.
2. Using partials
Using partials is always good to eliminate duplication. If your sidebar is very simple and is changed for every controller, you can render it as a partial. But if you're rendering different partials in the same controller, according to some state, it may be an indication that you have business logic in your views, which should be avoided.
3. Using the Cells gem
Very good design pattern when you have to render your sidebar from a different controller than the rest of the view each time.
It takes a lot of business logic out of the view, which sure is a good practice.
Here you have an action calling a view. Inside that view, there is a statement render_cell(:sidebar, params). This statement will do some business logic and render the view of the sidebar. It's as if the first action called other controller actions to render specific parts of your view (called cells)
If you make changes to the sidebar only, you may have to create other simple action, so that a javascript will request it. This action will call the render_cell(:sidebar) method again to respond with the view.
It's a very interesting approach.
Other ideas:
Your sidebar could be rendered only with javascript from the same
action.
Your sidebar could be rendered by an angular controller, and rails sends jsons with the sidebar objects. (look for "One page apps")
try something like this
<div class="sidebar">
<% if current_page?(controller => "friends", :action => "show") %>
<h4>New Friends</h4>
<% elseif current_page?(controller => "accounts", :action => "show") %>
<h4>Recent Activities</h4>
<% end %>
</div>
If the above code fits what you are trying to do(looks like this is what you want to achieve), then stick with it, else it may be beneficial to go with some gems. Also checkout helper page on how to use current_page? method. Hope it helps
I'm working on a small picture application. That I'm trying to do is build a counter to track how many times each image is clicked.
Right now I have in my view:
<% #galleries.each do |g| %>
<% for image in g.images %>
<div id="picture">
<%= render 'top_nav'%>
<%= link_to g.source, :target => true do %>
<%= image_tag image.file_url(:preview) %>
<% g.vote %>
<% end %>
<%= will_paginate(#galleries, :next_label => "Forward", :previous_label => "Previous") %>
</div>
Obviously this doesn't work, as the g.vote executes every time it's rendered, not clicked. Here's the vote method in my model:
def vote
self.increment!(:score)
end
I'm looking for a solution to run the vote method only when the image above is clicked. The links are to external resources only, not to a show action. Should I be building a controller action that's accepts a post, executes the vote, then redirects to the source?
Anyway, looking for some ideas, thanks.
I've done something similar, but keeping a count of how many times a Download link was clicked. This was awhile ago and I didn't know about Ajax at the time, but now I would recommend using jQuery (a great library in my opinion, but you could use something else) and do an Ajax call when the image is clicked that would execute some controller action which would increment that vote.
The other way, which is what I did in my scenario, and is what you talked about there, is creating a custom action in the controller that accepts a post. But I have to ask as well, does clicking on the image do something else in the behaviour of your website? For example, if when you click the picture, another random image is supposed to come up, that means you'll already have an action to load a new image and it be easy to stick the vote up in there before showing a new image. Otherwise you'd have to create the new controller action. If that's the case, the Ajax would be more efficient as the user wouldn't see a momentary flash as the page was refreshed (especially bad if the refresh time is long).
This is probably easy but I'm a bit of a newbie on wrapping my head around these things sometimes.
Synopsis: I'm trying to make a checklist application that technicians go through and answer questions about what has been completed or done in the field. The technicians then submit this for review. The questions are created, managed, and updated by the managers.
UPDATE
I'm a designer, so I naturally magnetize to PS. Here's a photo of the concept: http://screensnapr.com/u/a9k1ps.png
checklist model contains: header, subheader, question, and answer.
Everything is a string, except the answer field, which is an integer for a check box.
I'm not quite sure which RESTful page to start with after that though. I need the header displayed like this (in view), but editable/submittable through the check box all on one page.
This view has to DISPLAY the checklist and EDIT the checklist at the same time. The manager needs to be able to add new headers, subheaders, and questions, which the technicians can then answer.
<% #checklists.each do |checklist| %>
<h1> <%=h checklist.header %> </h1>
<h3> <%=h checklist.subheader %> </h3>
<ul>
<li>
<%=h checklist.question %>
<% form_for #checklists do |f| %>
<%= f.check_box("checklist", "answer") %>
<% end %>
</li>
</ul>
<% end %>
Would this work and would it best to stick this in the index or edit action? Would I be better doing a partial of some sort? nested_attributes? I'm a bit lost at this point because I'm trying to manage two actions (index, edit) within one file.
If you want a manager to update/modify the checkboxes and the technicians to fill in the forms, you need a couple of extra tables. One containing the questions and one containing the values that are checked. Also, it seems better to split the controller into two, one for each user type:
For the manager part you can simply make a controller like any other controller: using the index action to show all questions and the edit/update/etc actions to modify them.
For the technician part you need to define a project table, containing some information about the project the technician is working on. And a checkboxes table containing the project_id and the checkbox_ids, in order to link the checkboxes to a certain project.
See A Guide to Active Record Associations for more information about creating associations between tables.
Without looking at this further, I'm willing to bet you want
form_for checklist.question and POST to questions_controller, which would use the #update action.
I'm developing a simple rails app for my own use for learning purposes and I'm trying to handle 2 models in 1 form. I've followed the example in chapter 13 of Advanced Rails Recipes and have got it working with a few simple modifications for my own purposes.
The 2 models I have are Invoice and InvoicePhoneNumber. Each Invoice can have several InvoicePhoneNumbers. What I want to do is make sure that each invoice has at least 1 phone number associated with it. The example in the book puts a 'remove' link next to each phone number (tasks in the book). I want to make sure that the top-most phone number doesn't have a remove link next to it but I cannot figure out how to do this. The partial template that produces each line of the list of phone numbers in the invoice is as follows;
<div class="invoice_phone_number">
<% new_or_existing = invoice_phone_number.new_record? ? 'new' : 'existing' %>
<% prefix = "invoice[#{new_or_existing}_invoice_phone_number_attributes][]" %>
<% fields_for prefix, invoice_phone_number do |invoice_form| -%>
<%= invoice_form.select :phone_type, %w{ home work mobile fax } %>
<%= invoice_form.text_field :phone_number %>
<%= link_to_function "remove", "$(this).up('.invoice_phone_number').remove()" %>
<% end -%>
</div>
Now, if I could detect when the first phone number is being generated I could place a condition on the link_to_function so it is not executed. This would half solve my problem and would be satisfactory, although it would mean that if I actually wanted to, say, delete the first phone number and keep the second, I would have to do some manual shuffling.
The ideal way to do this is presumably in the browser with javascript but I have no idea how to approach this. I would need to hide the 'remove' link when there was only one and show all 'remove' links when there is more than one. The functionality in the .insert_html method that is being used in the 'add phone number' link doesn't seem adequate for this.
I'm not asking for a step-by-step how-to for this (in fact I'd prefer not to get one - I want to understand this), but does anyone have some suggestions about where to begin with this problem?
There is a counter for partial-collections:
<%= render :partial => "ad", :collection => #advertisements %>
This
will render "advertiser/_ad.erb" and
pass the local variable ad to the
template for display. An iteration
counter will automatically be made
available to the template with a name
of the form partial_name_counter. In
the case of the example above, the
template would be fed ad_counter.
For your problem of detecting whether a row is the first one or not, you could add a local variable when calling the partial:
<%= render :partial => 'mypartial', :locals => {:first => true} %>
As it would be much easier to detect in the main file, whether a row is the first or not I guess.
Instead of detecting whether a phone number is the first, you could also detect whether a phone number is the only one. If not, add remove links next to all numbers otherwise, do not display the remove link. Note that besides showing/hiding the link, you also need to add code, to prevent removing of the last number by (mis)using an URL to directly delete the number instead of using your form.