I'm following the tutorial found here. It's simple, and I've followed the instructions exactly to step 6.7. At this point, I get the error
undefined method `each' for nil:NilClass
when I try to access index.html.erb on the rails server.
I know the database is working fine, because I can do everything mentioned in step 6.3, create new posts and show/edit/destroy them with absolutely no problems.
Specifically, the issue is with the line
<% #posts.each do |post| %>
and it's essentially claiming that #posts is nil.
I appreciate any help for this ROR newbie! Thanks.
index.html.erb
<h1>Hello, Rails!</h1>
<table>
<tr>
<th>Name</th>
<th>Title</th>
<th>Content</th>
<th></th>
<th></th>
<th></th>
</tr>
<% #posts.each do |post| %>
<tr>
<td><%= post.name %></td>
<td><%= post.title %></td>
<td><%= post.content %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, :confirm => 'Are you sure?',
:method => :delete %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to "My Blog", posts_path %>
posts_controller.rb
class PostsController < ApplicationController
# GET /posts
# GET /posts.json
def index
#posts = Post.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #posts }
end
end
In order for the views to work fine in Rails they must be inside the correct directory. This is one of the many implementations of the so called "Convention over Configuration" that Rails loves.
So, if you have a method index and this method is inside a controller named PostsController, you must have a view named index inside the directory views/posts/. This way, Rails will know that it have to render this view when a get to this method is processed.
About a good tutorial, I would recommend this one. It is extense and covers a lot of things that are not just related to Rails itself, like deploying on Heroku and a little CSS.
Related
I am working on a super simple newsletter application, and I'm confused about this error. Why is there a nil class? I am only asking it to render, so why cant I put a redirect_to where the render call is?.
<% if admin_signed_in? %>
<p id="notice"><%= notice %></p>
<h1>Subscribedusers</h1>
<table>
<thead>
<tr>
<th>Email</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #subscribedusers.each do |subscribeduser| %>
<tr>
<td><%= subscribeduser.email %></td>
<td><%= link_to 'Show', subscribeduser %></td>
<td><%= link_to 'Edit', edit_subscribeduser_path(subscribeduser) %></td>
<td><%= link_to 'Destroy', subscribeduser, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Subscribeduser', new_subscribeduser_path %>
<% else %>
<%= render '/' %>
<% end %>
Why does this part of the code <%= render '/' %> trigger an undefined method 'empty?' for nil:NilClass error?
Since your desire is to return the user to the home page, instead of
render '/'
you should use
redirect_to root_path
The difference is render prepares the output to be displayed as the result of the current request and redirect_to commands user's browser to make a new request at specified url.
While it can be possible to render the contents of your home page in an arbitrary action, this is rarely desirable. One downside is the page url would not automatically update to your site's root in the browser's address line.
As a side note, render '/' is not a correct syntax. render generally accepts a hash of options and not a string.
Why do you have an <% else %> clause without any conditional loops? And what are you trying to call with <% render '/' %>? Are you trying to call the index page? If so, you can specify by saying <% render "index" %> .
So you don't need if and else block in view side for page redirect to root path.
From your controller's whatever action you need following code.
if admin_signed_in?
redirect_to root_path
end
also remove if and else block from view.
I've been banging my head against this for a while. I know it's a simple problem, and I've reviewed other code examples where I'm doing this successfully, but, I'm completely stumped.
I'm getting an error "undefined method `page_leads' for nil:NilClass" when I try to go to the "Show" page. On my landing_pages "show" page I'm trying to show the leads that came in via that page.
My show page code for this is:
<table class="table table-striped">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Score</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #landingpage.page_leads.each do |page_lead| %>
<tr>
<td><%= page_lead.fname %></td>
<td><%= page_lead.lname %></td>
<td><%= page_lead.score %></td>
<td><%= link_to 'Show', page_lead %></td>
<td><%= link_to 'Edit', edit_page_lead_path(page_lead) %></td>
<td><%= link_to 'Destroy', page_lead, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
My landing_page model has:
has_many :page_leads
My page_lead model has:
belongs_to :landing_page
My controller code for the "show" method for both landing_pages and page_lead is:
def show
#landing_page = LandingPage.all(landing_page_params)
end
On my page_leads table I have the "landing_page_id" field so I can associate the landing page to the lead.
Any ideas what I'm doing wrong?
Thanks in advance
Your controller action does not load any instance of a model. You expect it to load an instance of a LandingPage (usually the one in params[:id] for a show action). So your controller should assign it:
# `GET /landing_pages/:id`
def show
#landingpage = LandingPage.find( params[:id] )
end
It is because your #landingpage instance variable is not defined when you run that code.
Basically, in your controller's action, you should have something like:
def show
#landinpage = ... # insert your definition here
# rest of your controller's action
end
I am making a resume application to list my employment history, education history and other responsibilities. This is my first rails application on my own without a tutorial, but much of what I do is just following the same actions. All the code is here: https://github.com/victorman/portfolio
Quick summary. I ajaxed my app a bit, and got it to work. But I had a template with the exact same html as part of a view, so I replaced that portion with a render :partial.... The result was twice the html as before. Below is a more detailed description of what I did to the app.
I made two scaffolds, one for Jobs and one for Categories. Jobs has a foreign key to categories.
I made the Jobs view list a link for each category. The jobs#index controller then only finds the rows in the jobs table for that category.
Then I decided to throw some ajax in there so that clicking a link would only reload the relevant data. I added a respond_to at the end of the jobs#index method.
def index
#find which jobs to display based on category_id in the url params
#if no category_id param is given default to 1
unless params.has_key? :category_id
#jobs = Job.find(:all, :conditions => {:category_id => 1})
else
#jobs = Job.find(:all, :conditions => {:category_id => params[:category_id]})
end
respond_to do |format|
format.html
format.js #index.js.erb
end
end
I made a index.js.erb file that retrieves the new data and replaces the old.
var jobs = $("<%= escape_javascript(render(:partial => #jobs))%>").hide();
$("#jobs_table").replaceWith(jobs);
$("#jobs_table").fadeIn();
I added remote: true to the links in the jobs index.html.erb file.
<ul>
<% Category.all.each do |category| %>
<li><%= link_to category.name, { :controller => "jobs", :category_id => "#{category.id}" }, :class => "category_link", remote: true %></li>
<% end %>
</ul>
And I made the template partial where the jobs were displayed. it would never find _jobs.html.erb so i had to name it _job.html.erb
<tbody id="jobs_table">
<% #jobs.each do |job| %>
<tr>
<td><%= job.organization %></td>
<td><%= job.location %></td>
<td><%= job.details %></td>
<td><%= job.start_date %></td>
<td><%= job.end_date %></td>
<td><%= link_to 'Show', job %></td>
<td><%= link_to 'Edit', edit_job_path(job) %></td>
<td><%= link_to 'Destroy', job, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
after all that it worked but I still hadn't DRY'd up the code so I removed the repeated section from index.html.erb which is in _job.html.erb (as shown above) and replaced it with this.
<%= render :partial => #jobs %>
and now it gives me two identical <tbody> tags with id="jobs_table". Why is this giving duplicate data?
You've got a lot to fix...
Create a nested route in your routes.rb:
resources :jobs
resources :categories do
resources :jobs
end
index.html.erb:
<h1>Listing jobs</h1>
<div>
<ul>
<% Category.all.each do |category| %>
<li><%= link_to category.name, category_jobs_path(category),
class: "category_link", remote: true %></li>
<% end %>
</ul>
</div>
<table>
<thead>
<tr>
<th>Organization</th>
<th>Location</th>
<th>Details</th>
<th>Start date</th>
<th>End date</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody id="jobs_table"><%= render partial: #jobs %></tbody>
</table>
<br/>
<%= link_to 'New Job', new_job_path %>
the index of jobs_controller.rb can (should) be refactored to:
class JobsController < ApplicationController
def index
#jobs = Job.where(category_id: params[:category_id] || 1)
respond_to do |format|
format.html
format.js
end
end
end
and the index.js.erb response also should be refactored to:
$("#jobs_table").html("<%= escape_javascript(render partial: #jobs) %>")
$("#jobs_table").fadeIn()
there are some naming issues which should be more pregnant like:
jobs instead of jobs_table
and
category instead of category_link
Also trying to find a Job belonging to Category with 1 is odd. Deal with a different response than a default Category with id 1 (hard coded ids are one of the worst things you can do).
The div around the Categories list is useless (keep your rendered HTML slim and readable).
The problem is due to not understanding when rails manipulates singular vs plural.
Calling render partial: #jobs automagically goes out to the partial _job.html.erb for each element in #jobs. But then the partial goes through each element again because of #jobs.each do |job|.
To fix it, in the render line, replace #jobs with "jobs" and rename _job.html.erb to _jobs.html.erb.
Alternatively, save a step by just replacing #jobs with "job" and keep the template name _job, but this reinforces an incorrect naming scheme.
index.html.erb:
<tbody id="jobs"><%= render partial: "jobs" %></tbody>
index.js.erb:
$("#jobs").html("<%= escape_javascript(render(partial: 'jobs'))%>")
Now it will just search literally for the _jobs template (_jobs.html.erb) and render it once as opposed to going to the singular version of the name and rendering that many times.
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 new to Ruby on Rails & to web programming.
In my application I have two models; Directorate which has_many :users, and User which belongs_to :directorate.
When creating a new user, I use <%= f.collection_select(:directorate_id,Directorate.all, :id, :name) %> in the new.html.erb form to assign the new user to specific directorate. However, I want to build a user-friendly interface for the dba that lists all directorates; and listing all users beside each directorate, with a link to assign any user to a specific directorate.
What I did is the following:
In Directorate model, I defined the following function:
def assign_user!(user)
user.update_attributes(directorate_id: #directorate)
end
and in the directorates controller, I defined the following action:
def assign_user
#directorate = params[:directorate]
assign_user! params[:user]
redirect_to directorates_url
end
Now, directorates/index.html.erb contains the following:
<h1>Listing directorates</h1>
<table>
<tr>
<th>Name</th>
<th>Info</th>
</tr>
<% #directorates.each do |directorate| %>
<tr>
<td><%= directorate.name %></td>
<td><%= directorate.info %></td>
<td><%= link_to 'Show', directorate %></td>
<td><%= link_to 'Edit', edit_directorate_path(directorate) %></td>
<td><%= link_to 'Destroy', directorate, confirm: 'Are you sure?', method: :delete %></td>
<%= #directorate = directorate%>
<%= render 'users_form' %>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New Directorate', new_directorate_path %>
and, -users_form.html.erb contains the following form (which is supposed to list all users beside each directorate, with a link to assign any user to a certain directorate):
<h1>Listing Users</h1>
<table>
<tr>
<th>User Name</th>
</tr>
<% #users.each do |user| %>
<tr>
<td><%= user.username %></td>
<td><%= link_to 'Assign to Current Directorate', {controller: 'directorates', action: 'assign_user', directorate: #directorate, user: user}, :method => :put %></td>
</tr>
<% end %>
</table>
<br />
Here is the problem, when listing directorates & click on the 'Assign to Current Directorate' I receive the following error:
http://127.0.0.1:3000/directorates/assign_user?directorate=4&user=5
ActiveRecord::RecordNotFound in DirectoratesController#update
Couldn't find Directorate with id=assign_user
Rails.root: /home/ehab/sites/IAMS
Application Trace | Framework Trace | Full Trace
app/controllers/directorates_controller.rb:61:in `update'
Request
Parameters:
{"_method"=>"put",
"authenticity_token"=>"L5tz3hv2IW0meE79qUq0/tjfGKwDlpC23hOeAWtmTvk=",
"directorate"=>"4",
"user"=>"5",
"id"=>"assign_user"}
It's clear that the params is submitting "id"=>"assign_user" which I don't want, what i want is "id"=>"directorate.id" (4 in the above example). What shall I do to fix this issue?!
first of all your routes should say that assign_user is a member method on a certain directorate object:
resources :directorates do
member do
put :assign_user
end
end
second you say you define assign_user! in Directorate model and assign_user in DirectoratesController but both methods imply that they share same object state like instance variable #directorate which is not true
your controller method assign_user should look vaguely like
def assign_user
#directorate = Directorate.find params[:id]
#user = User.find params[:user_id]
#directorate.assign_user! #user
end
and model method should look like
def assign_user!(user)
user.update_attributes(directorate_id: self.id)
end
and even that i would switch around to instead of telling Directorate to change user's attributes you would tell User to assign itself to whatever controller wants.
and the final bit is your link that assigns user to directorate:
link_to 'Assign to Current Directorate',
assign_user_directorates_path(#directorate, :user_id => user)
0 lines of code above were tested for even syntactical correctness, DO NOT copy-paste, read and understand