I am just starting out with Ruby on Rails and to practice, I am creating a simple blogging app. On the page I created to view the list of all posts, all the data that is passed to the page is being rendered in an array near the top of the page like so:
I can't figure out why the array is showing. Here's the controller for that page:
def index
#posts = Post.all
end
And heres the view:
<h1>Listing posts</h1>
<table>
<tr>
<th>Title</th>
<th>Text</th>
</tr>
<%= #posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.text %> </td>
</tr>
<% end %>
</table>
and for the route I have tried both:
get '/posts/(.:format)' => 'posts#index'
and
get '/posts' => 'posts#index'
Also as a side question, what does (.:format) do anyway? The page seems to work the same whether I include that in the route or not.
When you use an "=" sign in the view it renders the result in html:
<%= #posts.each do |post| %>
Change the above line to:
<% #posts.each do |post| %>
The format is only useful when you want to render multiple formats (default is html), but you could call the page with a ".xls" or a ".json" etc and then have code in your controller to respond to those formats.
Related
This question already has answers here:
Rails: An elegant way to display a message when there are no elements in database
(10 answers)
Closed 8 years ago.
I'm a newbie at Rails and I'm having trouble wrapping my head around refactoring logic from views. Let's say I have a simple Post model. In the index view, I want specific content to be displayed if there are posts or not. Basically, if there are any posts, display this specific content or else this other content.
Here is my index.html.erb view for Posts:
<div class="content">
<% if #posts.any? %>
<table>
<thead>
<tr>
<th>Title</th>
<th>Content</th>
</tr>
</thead>
<tbody>
<% #posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.content %></td>
</tr>
<% end %>
</tbody>
</table>
<% else %>
<p>There are no posts!</p>
<% end %>
</div>
Now, the way I refactored this was by creating a couple of helpers and partials like so:
posts_helper.rb (which renders the partials according to the if logic):
module PostsHelper
def posts_any
if #posts.any?
render 'this_content'
else
render 'this_other_content'
end
end
end
In the partials, I just used the exact content in the if else statement.
_this_content.html.erb partial:
<table>
<thead>
<tr>
<th>Title</th>
<th>Content</th>
</tr>
</thead>
<tbody>
<% #posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.content %></td>
</tr>
<% end %>
</tbody>
</table>
_this_other_content.html.erb partial:
<p>There are no posts!</p>
Finally, the refactored index.html.erb (which would call the helper method):
<div class="content">
<%= posts_any %>
</div>
The problem is, I'm just not convinced that this is the correct Rails way of refactoring. If any of you could shed some light on this, I would highly appreciate it!
Thanks!
You're doing it right, and better than many people I know. :)
A few minor adjustments...
I would move the render from the helper to the erb, and just use the helper to return the right name of what to render.
Your erb code and helper code:
<%= posts_any %>
def posts_any
if #posts.any?
render 'this_content'
else
render 'this_other_content'
end
end
I suggest:
<%= render posts_any %>
def posts_any
#posts.any? ? 'this_content' : 'this_other_content'
end
Next, I personally like to render a collection using a partial.
Yours:
<% #posts.each do |post| %>
I suggest:
<%= render partial: "post", collection: #posts %>
And in the comment below, user kyledecot suggests even terser:
<%= render #posts %>
Then create the file _post.html.erb like this:
<tr>
<td><%= post.title %></td>
<td><%= post.content %></td>
</tr>
Some developers think that it's overkill to render a collection using a partial, in the case where the partial is not used anywhere else.
I personally think it's helpful, and especially useful when a project has multiple coders some of whom may be changing the table row data results.
What we are trying to do is to store a chunk of erb code in a string and then render the code in run time in erb.
Here is the chunk of erb code which is stored as string:
<tr>
<th>#</th>
<th><%= t('Date') %></th>
<th><%= t('Project Name') %></th>
<th><%= t('Task Name') %></th>
<th><%= t('Log') %></th>
<th><%= t('Entered By') %></th>
</tr>
<% #logs.each do |r| %>
<tr>
<td><%= r.id %></td>
<td><%= (r.created_at + 8.hours).strftime("%Y/%m/%d")%></td>
<td><%= prt(r, 'task.project.name') %></td>
<td><%= prt(r, 'task.task_template.task_definition.name') %></td>
<td><%= prt(r, :log) %></td>
<td><%= prt(r, 'last_updated_by.name') %></td>
</tr>
<% end %>
t() is the translation method for internationalization.
How can we insert the above erb code stored in string back to erb file below for rendering (in pseud code) ?
<table class="table table-striped">
<% erb_code = retrieve(chunk_of_erb_code)%>
<% erb_code here for rendering %>
</table>
Is there a solution for the problem? Thanks for help.
UPDATE:
Working code with render inline (by kamesh):
<% erb_code = find_config_const('task_log_view', 'projectx')%>
<%= render inline: ERB.new(erb_code).result(binding) %>
For a good practice, variable erb_code could be moved into the controller.
I think i got your question.
you can append any html string in erb using
in view:
<%= render inline:"<p>new Field</p>"%>
or
<%= render inline: "<% products.each do |p| %><p><%= p.name %></p><% end %>" %>
or
in controller as:
render inline: "<% products.each do |p| %><p><%= p.name %></p><% end %>"
writing it in any _xyz.html.erb or xyz.html.erb and also can be used from controller, as well. for more check following link. in sub topic - 2.2.6 Using render with :inline.
rails guide
I have checked working of this. Let me know in case of any issue.
You definitely want to do it with partials or helpers, because the solution you are requesting for is complicated and confusing.
But if you really need to implement this solution, you would have to create a .html.erb.erb file, it would be interpreted by erb twice.
Given the following helpers
def print_one
"1"
end
def print_a_method
"<%= print_one %>"
end
Pass 1, RoR interpret the html.erb.erb file, which originally look like this:
<%= "<%=" %> print_one.to_i + print_one.to_i <%= "%>" %>
<%= print_a_method %>
<%= 5 + 3 %>
The trick in first line is to "generate the erb tags for the second pass": <%= "<%=" %> and <%= "%>" %> that will become <%= and %>, and the rest of the first line is not interpreted during pass 1.
On the other hand the second line will be entirely interpreted during this pass, and the output of print_a_method will be placed in the file for it to be interpreted during the second pass.
The third line is interpreted as well and output its result.
Pass 2, RoR takes the result of the first pass which is now a .html.erb file. Internally it would look like this
# As you can seem the erb tags was generated, and now the erb code is ready for pass 2
<%= print_one.to_i + print_one.to_i %>
# The second line was interpreted and its result is erb code that will be interpreted during pass 2
<%= print_one %>
# the third line was interpreted and give the following output
8
Final render would be the .html file where the file from pass 2 is interpreted and that would look like this
2
1
8
Seems like a job for partials.
# app/views/some_folder/_my_erb_partial
<%= t(whatever) %>
...
<table class="table table-striped">
<%= render 'some_folder/my_erb_partial' %>
</table>
Update.
If you need to store ERB templates in your database and render them in real time, take a look at render erb from database into view problem please help!
However, I don't know if this is necessarily your best option, as it could lead to security issues and other issues (namely, if you change code, your templates stored in the database would likely break). In most cases, it would be best just to make a new model for whatever you need to do, and do it the Rails way (with partials).
(I was able to simplify my original answer quite a bit.)
You can create application helpers like this:
helpers/application_helper.rb:
module ApplicationHelper
def my_erb_converter(template)
erb = ERB.new(template)
erb.result
end
def t(str)
"***#{str}***"
end
end
Then in an action do:
include ApplicationHelper
class SomeController < ApplicationController
...
...
def some_action
#html = my_erb_converter("<div><%= t('hello') %></div>")
...
end
Then in your view:
<table class="table table-striped">
<%= raw #html %>
</table>
This also works for me:
module ApplicationHelper
def convert_erb(template)
erb = ERB.new(template)
erb.result
end
def t(str)
"***#{str}***"
end
def get_erb
"<div><%= t('hello') %></div>"
end
end
View:
<table class="table table-striped">
<%= raw convert_erb(get_erb) %>
</table>
How can I return data from the database on another page?
I can file this under: views / posts / index.htm.erb
<h1>Listing posts</h1>
<table>
<tr>
<th>Titulo</th>
<th>Conteudo</th>
<th>Categoria</th>
<th>Criado em</th>
<th></th>
<th></th>
<th></th>
</tr>
<% #posts.each do |post| %>
<tr>
<td><%= post.titulo %></td>
<td><%= post.conteudo %></td>
<td><%= post.category.name %></td>
<td><%= post.created_at.strftime("%d/%m/%Y") %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Delete', post, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New Post', new_post_path %>
And I wanted to display these values on another page: views / home / blog.html.erb
How do I do this? Could you explain all the steps so that I can display these values in my other page.
Thanks Kocur4d
but how do I get only some information? eg: I would like that to appear in the title of the post page like this way (in blog.html.erb):
<div class="post-title">
<h2 class="title"> <a href="link_to_post"> **<% = post.titulo%>** </ a> </ h2>
</ div>
Step 1. Create controller
In your app root directory run:
rails g controller home blog
Modify controllers/homes_controller.rb :
class HomesController < ApplicationController
def blog
#posts = Post.all
end
end
Your controllers/posts_controller.rb should be already set up. Minimum what you need for your question is to have index method defined you might have other methods as well:
class PostsController < ApplicationController
def index
#posts = Post.all
end
end
Step 2. Extract Partial
change views/posts/index.htm.erb :
<h1>Listing posts</h1>
<%= render partial: 'shared/posts', object: #posts %>
<%= link_to 'New Post', new_post_path %>
create/modify views/home/blog.html.erb :
<h1>Listing posts</h1>
<%= render partial: 'shared/posts', object: #posts %>
<%= link_to 'New Post', new_post_path %>
create views/shared/_posts.html.erb :
<table>
<tr>
<th>Titulo</th>
<th>Conteudo</th>
<th>Categoria</th>
<th>Criado em</th>
<th></th>
<th></th>
<th></th>
</tr>
<% posts.each do |post| %>
<tr>
<td><%= post.titulo %></td>
<td><%= post.conteudo %></td>
<td><%= post.category.name %></td>
<td><%= post.created_at.strftime("%d/%m/%Y") %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Delete', post, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
</table>
Step 3. Set up routes.
You should have something like this in your routes.rb file:
resources :posts or match 'posts/index' => 'posts#index'
add this to config/routes.rb:
match 'home/blog' => 'home#blog'
so it might look like this(there is few variants):
config/routes.rb:
YourAppName::Application.routes.draw do
root to: 'posts#index'
resources :posts
match 'home/blog' => 'home#blog'
end
Now when you start rails server(assuming standard configuration) and visit:
127.0.0.1:3000/posts/index and 127.0.0.1:3000/home/blog
you should see same content.
This should work copy-and-paste but I could make some typos and other small mistakes(hope not, if ill find any ill try to edit them asap). In general look at it as you need 3 steps to forward http request down your rails application stack.
Map url to controllers using routes.
Create controllers and inside prepare data for views.
Display data in Views.
Look around in Rails Guides, Rails for Zombies and Rails Tutorial for more info.
---------Upadate to your second question-----------
I don't really understand what would you like to achieve?? At the moment both index.html.erb and blog.html.erb showing the same data, that was what you ware asking for?
post representing one post and is available in sharde/_posts.html.erb. You can't reference it from index.html.erb or blog.html.erb.
#posts represents all the posts and its available in index.html.erb or blog.html.erb.
render partial: 'shared/posts', object: #posts -- this line say "Hey man! Paste here content of shared/posts file, and btw I have here a local variable #posts so if you need to use that date in shared/posts file Ill name it posts from in side there"
To make them look different modify both files and part that will be identical for both of them is in a sharde/_posts.html.erb.
Try for example remove this line:
<td><%= post.category.name %></td>
from shared file to see what is going to happen.
Add some html tags and thinker with it.
Rails has may helper methods available' to find out about them check the links I give you and google, google, google.
Try to add some links with link_to helper
In your home controller, for the blog method, set #posts as you need...
Maybe
#posts = Post.all
I'm using Rails 3, ActiveAdmin and Kaminari.
I have this on the documents.rb file (activeadmin file).
collection_action :index do
#page_title = "Documents"
#shipments = Shipment.page(params[:id]).per(3)
render '_invoices', :layout => 'active_admin'
end
The pagination links are displayed fine. I click the pagination links and I do get this in the URL http://localhost:3000/admin/documents?page=4 so it seems fine. The problem is, it always displays the same records, they don't change according to the page.
This is what I have as the partial that is being rendered...
<table class="index_table">
<tr>
<th>File #</th>
... buncla th's
</tr>
<% #shipments.each do |shipment| %>
<tr class="<%= cycle("odd", "even") %>">
<td><%= link_to shipment.file_number, admin_shipment_path(shipment) %></td>
...buncha cells...
</tr>
<% end %>
</table>
<div id="index_footer"><%= paginate #shipments %></div>
Use the page parameter and not id.
#shipments = Shipment.page(params[:page]).per(3)
So, i'm trying to follow along with this example. I'm trying to translate it to my own own project where I have a set of rows that are displayed based on the results of applying the search criteria in a first form. I'm trying now to put a second form around the results to provide the administrator with checkboxes to be able to edit several of the rows displayed at the same time. however, when i try to put a form around the results, the results disappear altogether.
Here's the relevant piece of my controller:
def index
#search = Distribution.workflow.search(params[:traits_searchable_search])
respond_to do |f|
f.html {
#report = #search.paginate(:page => params[:page])
render :action => 'index'
}
f.csv do
send_data #report.to_csv, :type => "text/csv", :filename => "distribution_workflow_report.csv"
end
end
end
the view is nothing special. but i'm trying to wrap this tag (i've also tried removing the :method => :put piece and it's worth noting that the path provided to the form_tag is the page that's being displayed for now until i figure out how i'm going to get the routing to work):
<% form_tag admin_distributions_workflows_path, :method => :put do %>
around this table:
<table class="standard-grid">
<tr>
<th class="first"></th>
<th>ID</th>
<th>Customer</th>
<th>Customer Email</th>
<th>Resume URL</th>
<th>Partner</th>
<th>Partner Email</th>
<th>Status</th>
<th>Assigned To</th>
<th>Comments</th>
<th></th>
</tr>
<% #report.each do |row| %>
<tr>
<td><%= check_box_tag "row_ids[]", row.id %></td>
<td>
<%= row.owner.id %>
</td>
....
</td>
</tr>
<% end %>
</table>
<% end %>
Since Rails 3 you have to use <%= format with form_for and form_tag
<%= form_tag