Can't link to objects belonging to a category - ruby-on-rails

I have a method that groups all my book categories together
def self.categories_list
joins(:books).
select('categories.id, categories.name, count(*) AS books_count').
group('categories.id, categories.name').
order('books_count DESC')
end
I can then output them to my view like so
#bookcategories = Category.categories_list
What I want to do then is link to all the books belonging to say 'Computing' by clicking 'Computing' in the view
<% #bookcategories.each do |b| %>
<li><%= link_to b.name, category_path(b.name) %></li>
<% end %>
This should take me to my show action of my category controller
def show
#category = Category.where(:name => params[:name]).first
#categorisedbooks = #category.books #get me all books that have the category name
end
and the view for the show action
<div class="container">
<div class="row ">
<div class="span12">
<% #categorisedbooks.each do |c| %>
<%= image_tag c.avatar.url(:medium), :class=> "allBooksCover" %>
<% end %>
</div>
</div>
</div>
So when I click 'Computing' for example I get
undefined method `books' for nil:NilClass
and the params are being passed as
Parameters:{"id"=>"Computing"}

So, you need in your show action
#category = Category.where(:name => params[:id]).first
# etc

Related

undefined method `each' for nil:NilClass..why?

i've been working on new app it's like IMDB and i added category model which it works fine with the association but i'm having problem in Displaying movies by category in category controller:
def show
#category = Category.find(params[:id])
#category_movies = #category.movies
end
in the category show page:
<h align = "center"><%= "Category: " + #category.name %></h1>
<%= render 'movies/movies', obj:#category_movies %>
and in index i did:
<div class= "row">
<% #movies.each do |movie|%>
<div class="col-sm-6 col-md-3">
<div class="thumbnail">
<%= link_to (image_tag movie.image.url(:medium), class: 'image'), movie %>
</div>
</div>
<% end %>
</div>
so i got an error undefined method `each' for nil:NilClass
any ideas
in your partial, you use #movies but in the controller, you are calling it #category_movies - you will need to use the same variable name, or use local variables.
eg with local variables:
<%= render 'movies/movies', :movies => #category_movies %>
# and in the partial
<% movies.each do |movie|%>
Note: not tested for bugs and typos...
Instance variable #category_movies must be the same in the controller and in the views :)
#movies is not declared so it's nil !

Rails retrieving all records in show controller

In my rails category show controller for categories I have it setup like this
def show
#categories = Category.find_by(params[:name])
end
But when I visit this controller it returns all records of products found in the category instead of single category.
Here is the code in my view controller for category
<div class="grid">
<% #categories.products.each do |product| %>
<%= link_to product_path(id: product.slug, category_name: product.category.name), class: "card" do %>
<div class="product-image">
<%= image_tag product.productpic.url if product.productpic? %>
</div>
<div class="product-text">
<h2 class="product-title"> <%= product.name %></h2>
<h3 class="product-price">£<%= product.price %></h3>
</div>
<% end %>
<% end %>
</div>
What am i doing wrong here?
First of all, for security purposes, you should never trust the params hash to retrieve records. Rails will "make the data safe" if you use a hash as your arguments. Use this code below:
def show
#category = Category.find_by(name: params[:name])
end
Second, usually on a show page, you only want to retrieve one record and therefore the variable should be named as singular. I corrected that above.
Third, it helps if you use proper indenting when posting examples. It makes it easier for us to help you.
Fourth, the line below (I changed #categories to #category) is basically saying: "Now that I have this single category, find all the products associated with it in the products table and put them into the |product| variable for iteration"
<% #category.products.each do |product| %>
I'm not sure what you want to do with the category, but if you keep this line of code, it will always show you all the products. Maybe you only want to show the most recent 3, in which case you could do something like this:
In your controller:
def show
#category = Category.find_by(name: params[:name])
#recent_products = #category.products.order(created_at: :desc).limit(3)
end
In your view:
<div class="grid">
<% #recent_products.each do |product| %>
<%= link_to product_path(id: product.slug, category_name: product.category.name), class: "card" do %>
<div class="product-image">
<%= image_tag product.productpic.url if product.productpic? %>
</div>
<div class="product-text">
<h2 class="product-title"> <%= product.name %></h2>
<h3 class="product-price">£<%= product.price %></h3>
</div>
<% end %>
<% end %>
</div>
You can do this way
in your controller you can write this code
def show
#category = Category.find_by_name(params[:name])
end
and in your view it will work
<div class="grid">
<% #category.products.each do |product|%>
// place your code what you want to display
<% end %>
</div>
I hope it would help you and still if you have any concern please let me know.

How to call a method from Application Controller in any given controller test

I have a controller that POSTs a new instance of a model into a database after the user fills out a form. This form is created using an each do that loops over a series of inventory items defined in the Application Controller.
In other words, this is the view code:
<%= form_for #requestrecord, :html=> {:id => 'form'} do |f| %>
<div class="col-xs-12">
<p><b>Items we have available</b></p>
</div>
<% #inventory.each do |category, list| %>
<div class="col-xs-2">
<div class="form-group box">
<h5> <%="#{category}"%> </h5>
<% list.each do |thing| %>
<%= f.check_box(:items, {:multiple => true}, "#{thing}") %>
<%= f.label(:items, "#{thing}") %>
</br>
<% end %>
</div>
</div>
<% end %>
There is a method in the application controller that defines inventory:
def inventory
#inventory = { some hash }
end
And then this method is called in the Requests controller that I'm trying to test:
def create
inventory
#requestrecord = Request.new(request_params)
end
The problem is in my Rspec controller test, I now have to manually define this inventory again like so:
before do
#inventory = { some hash }
end
Instead of doing this, is there a way to call the method from the Application Controller in the before statement? The #inventory is a rather long hash...
Thanks!
You can access your controller in rspec with 'controller', so
before do
#inventory = controller.inventory
end
should do the job!

update partial with object content in rails 4

Well, i have a problem, and i was wondering if it could be solved with rails only.
I have setup a view (home.html.erb) vith 3 partials, like this:
<%provide :title, 'Reader'%>
<div class = "row">
<div class = "span4">
<div class = "row">
<%= render 'layouts/add_subscription'%>
</div>
<div class = "row">
<%= render 'layouts/subscription_list'%>
</div>
</div>
<div class = "span8">
<div class = "row">
<%= render 'layouts/view' %>
</div>
</div>
</div>
where subscription_list shows up a list of links pointing to the list action after a redirection, each of them with the id of the subscription:
<ul>
<% current_user.subscriptions.each do |s| %>
<li><%= link_to s.url, "/list?s_id=#{s.id}" %></li>
<% end %>
</ul>
So, each of these links points to the list action in the controller, which tries to fetch the feed list of the subscription just clicked, and update the home view with the list of titles for the selected subscription:
def list
s_id = params[:s_id]
feed = ""
if !s_id.blank?
s = Subscription.find_by(id: s_id)
feed = Feedzirra::Feed.fetch_and_parse(s.url)
#render partial: "layouts/view", :locals => {:f => feed}
end
The problem is that I'm stuck at this point. I've tried to do a redirect_to home_path with feed as a parameter, and even a render (the line before the end of the list method) to see what happened, but nothing updates 'just' the layouts/view partial:
<ul>
<% if defined? feed and !feed.blank? %>
<% f.entries.each do |entry|%>
<li><%= entry.title %></li>
<% end %>
<% end %>
</ul>
So, I was wondering if it's possible to update the partial and see the result after a page reload using only rails methods, or if it can/must be done using javascript, and a clue to how to do this. Thanks in advance.
The goal you want to achieve is to show feed entries in the home.html.erb after clicking a link.
You can do it by pointing your links to the home action instead of list so that rails will automatically render your home.html.erb view and
you have to assign the instance variable #feed so it will be visible in your view.
You can do it like this (refactored a bit):
controller
def home
s_id = params[:s_id]
if s_id.present?
s = Subscription.find_by(id: s_id)
#feed = Feedzirra::Feed.fetch_and_parse(s.url)
end
end
layout/view
<ul>
<% if #feed.present? %>
<% #feed.entries.each do |entry|%>
<li><%= entry.title %></li>
<% end %>
<% end %>
</ul>
I'm not sure what is the path to your action, I assume here that home is the root ("/")
layouts/subscription_list
<ul>
<% current_user.subscriptions.each do |s| %>
<li><%= link_to s.url, "/?s_id=#{s.id}" %></li>
<% end %>
</ul>

Rails, link_to, unable to pass on a value

I am trying to achieve an unordered list of "Categories" in which if you click on a particular Category, all the photos(jags) that belong to that Category show on the screen. My view that includes the categories is:
<div id = "Categories">
<h2>Categories</h2>
<ul><% #cat.each do |c| %>
<li><%=link_to c.name, c,:controller => "category", :action => "show" %>
</li>
<% end %>
</ul>
my Category controller is:
def show
#jags = Jag.where("category_id = params[:id]")
if #jags.empty?
flash[:notice] = "No jags in this Category"
end
end
and lastly my show view is:
<%= render 'nav' %>
<div><% #jags.each do |j| %>
<%= image_tag j.image_url(:thumb)%>
<% end %>
</div>
The problem i am having is that I dont know how do i pass on my "particular category"(c) in the first view to the Category controller.
I tried making c an instance variable(#c) which apparently i cant do[formal argument cannot be an instance variable
'); #cat.each do |#c| ;#output_buffer.safe_concat('].
If I run this code I get an SQLlite error[SQLite3::SQLException: near "[:id]": syntax error: SELECT COUNT(*) FROM "jags" WHERE (category_id = params[:id])].
If you use RESTful controllers this should be enough:
<div id = "Categories">
<h2>Categories</h2>
<ul>
<% #cat.each do |c| %>
<li><%=link_to c.name, c %></li>
<% end %>
</ul>
Seeing as you're getting the ID for the Category in the controller, then you can just do
#category = Category.find params[:id]
in your controller. Also, clean up your link_to helper as per below.

Resources