Multiple views in Rails - ruby-on-rails

I have the following problem:
In Rails I have two Objects: Categories and Items
One category has many items and one item belongs to one category.
Okay. There are no problems.
But now, I want to display all existing categories in a sidebar on every page in my project.
I tried to do display them like:
<div class="sidebar">
<% #categories.each do |category| %>
<p><%= link_to category.title, category %></p>
<% end %>
</div>
My root controller is categories. On my starting page the code above will work without any problems.
But when I click on a category I get the following exception:
*You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.each*
Extracted source (around line #2):
2: <% #categories.each do |category| %>
How can I fix this problem?
Sorry for my bad English!

You forget to set the #categories variable in the controller.
You can either load the #categories in every action you need to display the sidebar or delegate the request to the view without setting an instance variable.
# in the controller
def action
#categories = ...
end
# or in the view
<div class="sidebar">
<% Category.all.each do |category| %>
<p><%= link_to category.title, category %></p>
<% end %>
</div>
If the code spans over multiple views/controllers, I would suggest you to extract the statement in a before_filter and/or a partial.

Related

Rails - how to write an index view?

I'm having trouble figuring out how to display an index.
In my organisation requests view folder, I have a file called index.html.erb.
In that file, I'm trying to list each organisation request. I've tried each of the following formulations:
<% OrganisationRequest.each do |OrgReq| %>
<% organisation_request.each do |OrgReq| %>
<% #organisation_request.each do |OrgReq| %>
<% #organisation_requests.each do |OrgReq| %>
In each case, I get an error that says:
formal argument cannot be a constant
I thought a constant meant something beginning with a capital letter. 3 of the above attempts don't begin with a capital letter.
It's also confusing to me since in my user index, I have <% User.each %> and I don't get an error message.
Can anyone see what's gone wrong? How do I ask for a list of objects?
If you have your data and view right, you should be able to fix with:
<% #organisation_requests.each do |org_req| %>
...
<% end %>
If we stick Rails conventions, we'd say that, you have a OrganisationRequests controller, has such content.
class OrganisationRequestsController < ApplicationController
...
def index
#your_local_variable = OrganisationRequest.find(...)
end
...
end
That is to say, you need to use, #your_local_variable inside view file.
<% #your_local_variable.each do |o| %>
....
<% end %>
If the variable inside index action is #organisation_requests, use that.

Rails - Display all questions by category

I have question and category model. Question model has category_id column.
class Question
belongs_to :category
end
class Category
has_many :questions
end
In my controller I have this:
def index
#categories = Category.all
#questions = Question.all
end
I would like to display all categories and all questions that belongs_to specified category. Also, I would like to display question numbers below each category and made links of them and later it will open new page with clicked question.
This is how I tried to do that:
<% #categories.each do |category| %>
<h1><%= category.name %></h1>
<% #questions.each do |question| %>
<ul>
<li><%= link_to question.id %></li>
</ul>
<% end %>
<% end %>
It should look like this but I get stuck:
Category1
1 2 3 4
Category2
1 2 3 4
Question: How to achieve that I display questions like is show above?
You can do it this way:
Controller:
def index
#categories = Category.all
end
View:
<% #categories.each do |category| %>
<h1><%= category.name %></h1>
<% category.questions.each do |question| %>
<ul>
<li><%= link_to question.id, question_path %></li>
</ul>
<% end %>
<% end %>
Since you said you want to display all of the categories, and the questions that belong to each of those categories, I'm assuming that the index action that you pasted in comes from your categories_controller.
One solution I can think of would be to change the instance variables inside your index. I don't really see a purpose for having the instance variable that references all of your Question objects. This is the one I'm talking about:
#questions = Question.all
Yea, get rid of that. You should be fine with just
#categories = Category.all
Since you want to display all of your categories, that instance variable is necessary. And since you mentioned you want to also display all of the questions that belong to each category, that instance variable is sufficient with the right view. You were on the right track, but instead, just use the #categories instance variable; forget about #questions. Here is what your view should probably look like (you were on the right track above):
<% #categories.each do |category| %>
<h1><%= category.name %></h1>
<% category.questions.each do |question| %>
<ul>
<li><%= link_to question.id, question_path %></li>
</ul>
<% end %>
<% end %>
Also note that in that first line of code, when you start a block, you don't need the <%= , You only need the <%. That's because that first line of the block is purely ruby in itself, it isn't actually getting printed to the resulting html.
Hope I helped a little bit!
* Also: I saw another answer on here which is missing something: When you use the <%= link_to %> helper, you need to specify the first argument which is the resulting markup (In this case you wanted the question.id) , AND ALSO A SECOND ARGUMENT, which is the path for the link to follow *

Rails - List a all items method in controller

I need to list all my lawns in one page and then all my bookings in another page. I am writing a method in my controller to list my all items in my database but the problem is either it displays 1 in the view or it produces an inheritance error(in the view) . What I have so far is a lawn that has_many bookings (should actually be has one booking) and a booking which belongs to a lawn and everything is controlled through Activeadmin. The error I get is
undefined method `description' for
Lawn::ActiveRecord_Relation:0x007f4451b00a58> I have modified the error a little bit so it can show over here.
Here is my controller code. A lawn has a title and a description so I am not sure why I get the error. I have put 2 different methods for lawn and booking but they are both not working. Here is my controller.
def display_lawns
#lawn = Lawn.all
end
def display_status
#lawn = Lawn.where("selected = ?", "true")
#bookings = #lawn.booking
end
And here is my view file which does not seem to work with the Lawn.all I also have a similar view file for the bookings with a few changes.
<h2><%= #lawn.description %></h2>
<ul>
<% #lawn.bookings.each do |booking| %>
<li>
<%= booking.description %>
<%= button_to "Select", update_booking_path(booking_id: booking), remote: true %>
</li>
<% end %>
</ul>
A couple of hints.
Instead of
#lawn = Lawn.where("selected = ?", "true")
Is better to add a scope in your model.
#lawn is an array of objects, so use plural.
def display_lawns
#lawns = Lawn.all
end
def display_status
#lawns = Lawn.all.where("selected = ?", "true")
end
#lawns is an array, so you can't use #lawn.description
#lawn.first.description works if you need the first item of the array
<h2><%= #lawns.first.description %></h2>
<ul>
<% #lawns.each do |lawn| %>
<li>
<%= lawn.description %>
<%= button_to "Select", update_booking_path(booking_id: lawn.booking), remote: true %>
</li>
<% end %>
</ul>
Lawn.all and Lawn.where(...) return an ActiveRecord::Relation, consisting of multiple lawns.
In your view, you try to display a lawn's description via #lawn.description, but #lawn is not a single lawn object, but a collection of lawn objects, and the collection does not have a description.
Either only show one lawn object, or loop over all the objects in #lawn (and rename it to #lawns).

How does one properly create a second view for a controller in Rails?

I am quite new to Rails and have created a second controller to display a list of items without providing the edit and destroy options. (it is meant as the front end) I am now trying to create a show view for that particular listing but am not sure what steps take. Having created a second view file, I seem unable to access information in the model, receiving undefined variable errors. I am able to access them in the main index view for the controller so I expect there is either something in routing or the controller itself that I have to add.
Thanks in advance for your help.
Updated October 1, 2013 16:15PST
The second view called show.html.erb, just contains the following code to see if it will pull up the data:
<p><%= plant.botanical_name %></p>
The first view, called index.html.erb, contains this and it pulls the variables correctly:
<h1>Plant Display</h1>
<% #plants.each do |plant| %>
<div class="listingItem">
<div class="showThumbnail">
<%= link_to display_show_path do %>
<%= image_tag plant.photo.url(:medium) %>
<% end %>
</div>
<div class="listingItemInformation">
<p><%= plant.botanical_name %></p>
<p><%= plant.family %></p>
<p><%= plant.common_name %></p>
</div>
</div>
<div class="clear">
</div>
<% end %>
The controller just has this:
class DisplayController < ApplicationController
def index
#plants = Plant.order(:botanical_name)
end
end
Also, in terms of versions: Rails 4.0.0.rc1 and Ruby 1.9.3p392
The plant variable in the index view is actually an argument to the iteration block. When you write this:
it iterates over all the plants in #plants, and on each iteration plant is assigned to a plant. #plants itself is defined in the index controller method.
Your show view doesn't work because it uses plant but does not define it anywhere. Since you only want to show a single plant, what you want to do is to create a #plant variable in the show controller method and use it in the code instead of plant. So your controller should look something like this(didn't test it):
class DisplayController < ApplicationController
def index
#plants = Plant.order(:botanical_name)
end
def show
#plant = Plant.find(params[:id])
end
end
and your view:
<p><%= #plant.botanical_name %></p>
Also, in the index view, you will want to change
<%= link_to display_show_path do %>
to
<%= link_to display_show_path(plant) do %>
so it will link to the currently iterated plant.

Dynamic data in rails partial view

I've just started to use Partials in my rails application, at the moment i have the following code in my application.html.erb
<%= render 'categories/categorieslist' %>
This links to _categorieslist.html.erb in my views/categories/ folder
At the moment this partial contains hard coded hyperlinks
<ul class="unstyled">
<li style="padding-bottom:5px">Item A»</li>
<li style="padding-bottom:5px">Item B»</li>
</ul>
My aim is to have these categories coming from the database, e.g
<ul class="unstyled">
<% #categories.each do |category| %>
<li style="padding-bottom:5px"><%= category.name %> » </li>
<% end %>
</ul>
I have tried adding a categorieslist method in the categories controller e.g
def categorieslist
#categories = Category.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #categories }
end
end
but this is not being called by the partial (and i don't feel this is even the correct way to do it), and is showing the error
NoMethodError in Store#index
on the line <% #categories.each do |category| %>
My question is how do i pass into the partial in the application.html.erb file, the categories object that usually would come from a controller method in the categories controller?
Any help would be great.
You can send locales with your partial call in your view and pass variables to that partial.
For example (this is a partial shortcut):
Your view from which you call the partial
<%= render 'categories/categorieslist', :all_categories => #categories %>
Your partial categories/_categorieslist.html.erb (note there is no # with the variable)
<ul class="unstyled">
<% all_categories.each do |category| %>
<li style="padding-bottom:5px"><%= category.name %> » </li>
<% end %>
</ul>
For further information (and the long version), see 3.4.4 Passing Local Variables in the Rails Guides.
I'd use a collection for this:
<%= render 'categories/categorieslist', :collection => #categories, :as => :category %>
This renders a collection of items. In this case, all the categories. You can also pass it a custom name with the :as => .
Then in your partial you only include the stuff you want the items in the collection to render:
<li style="padding-bottom:5px"><%= category.name %> » </li>
The -ul- isn't included as it would be rendered multiple times. You'll need to wrap it around your render tag.
The result is the same as the suggestion #timbrandes outlined, (check out docs he linked to).
I've heard :collection gives you performance improvements.
http://rails-bestpractices.com/posts/38-use-render-collection-rails-3-when-possible
That's not the right way to do it, and your question is rather confusing.
I'd say that you still have to read a rails book. You seem to be still a bit too fresh
Anyway, controller methods usually represent http requests. And they are invoked accordingly to what is defined in the config/routes file. Views (*.erb) do not usually invoke controller methods. If they do so, they do it through an ajax request.
Data is passed from actions to the views through controllers instance variables.
If you want to invoke any methods within the views, they should be defined in helpers. Still, the only data they will manipulate is the one passed from controllers as instance variables.

Resources