Cant find model with id error - ruby-on-rails

My screenshot
I have messages speaker models.
I want to display number of messages each speaker posted on pages index page. When i insert #speaker = Speaker.find(params[:id]) it dispalys error Couldn't find Speaker with 'id'=. I dont understand what am i doing wrong.
my pages controller
class PagesController < ApplicationController
def home
#messages = Message.all.order("created_at DESC")
#speakers = Speaker.all
#speaker = Speaker.find(params[:id])
#count = #speaker.messages.count
#listeners = Listener.all
end
def about
end
def show
#speaker = Speaker.find(params[:id])
end
end
and my home view
<%= #count %> Messages

I think I need to see your routes.rb and the whole home view to better understand. My guess is that you are not actually passing the parameter for it to find.
For example, if your route looks something like this example route:
# Example of regular route:
# get 'products/:id' => 'catalog#view'
When you go to the URL products/1, it knows to pass the parameter id of 1 (params[:id] = 1) to the controller. Otherwise, you need to pass it into the GET request somehow like through a link. Since it is your home page, I doubt that is the intended set up of your app.
My guess is you are attempting to loop through all speakers on the home page. In that case, you can achieve the same effect but with simpler code. This is just a guess, but you may be able to do something like this in your controller and views:
class PagesController < ApplicationController
def home
#speakers = Speaker.all
end
end
<% #speakers.each do |speaker| %>
<%= speaker.name %>: <%= speaker.messages.count %> messages
<ul>
<% speaker.messages.each do |message| %>
<li><%= message.body %></li>
<% end %>
</ul>
<% end %>
This will print out the speaker's name and message count and then all their messages, assuming you set up the relationship between them in your model.

Related

Rails use the same endpoint instead of two new

In my app I need to display purchased Book in one page and planned_purchase Book in other page. The view will be the same so my question is - do I need to create new controller method and routes to display both or can I use e.g. Index and somehow display two different values depending on request?
current code below:
class BooksController < ApplicationController
before_action :fetch_conversation
def index
#planned = Book.planned_purchase
#purchased = Book.purchased
end
end
class Book < ApplicationRecord
scope :purchased, -> { where(purchased: true) }
scope :planned_purchase, -> { where(purchased: false) }
end
As I can understand: you can do this thing using a single controller GET action.
So, you've this BooksController and index action, which I assume can be accessible via books_path.
You can modify the index method, as follows to accept a new parameter by which you can filter the books:
def index
case params[:filter]
when 'purchased'
#records = Book.purchased
when 'planned_purchase'
#records = Book.planned_purchase
else
#records = Book.all
end
end
Now, you have a view page books/index.html.erb for this index action. Let's break this into 2 separate partials.
In books/index.html.erb:
<% if params[:filter] == 'purchased' %>
<%= render "partial_for_parchased" %>
<% elsif params[:filter] == 'planned_purchase' %>
<%= render "partial_for_planned_parchased" %>
<% end %>
Inside those partials you can modify the view based on the category.
Now, to get those two different page, you need to define 2 separate urls:
<%= link_to 'Purchased', books_path(filter: 'purchased') %>
<%= link_to 'Planned Purchased', books_path(filter: 'planned_purchase') %>
As your, def index, is a GET method and not depending on the strong parameters, so you don't need to add filter in your params.required(:book).permit(...)
Hope I covered all the areas!
I think the answer should be pretty simple and straight.
You can just pass a parameter to the index method and filter records inside it and return them.
def index
case params[:filter]
when 'purchased'
#records = Book.purchased
when 'planned_purchase'
#records = Book.planned_purchase
else
# get all records or throw an error
end

How to filter by params and user input in Rails

I am trying to display only the rows that belong to certain states in my application. I can do it the long way in Javascript, but I would prefer to better understand Rails and queries in the controller. I want to take the users to another page and then show them only that the companies in that state. It would be great to not have to link them to another page. Does anyone know how to do this?
Here is what I have in my controller
def vendors
#vendors = Collective.where(sort: 'Vendor').all
#vendors = #vendors.where(params[:state])
end
My route
get '/vendors/:state', to: 'collectives#vendors'
Then I use the stereotypical method to print a table in a html.erb file.
<% #vendors.each do |company| %>
<tr>
<td><%= company.name %></td>
<td><%= company.state %></td>
etc...
Should your controller code change the where as follows:
def vendors
#vendors = Collective.where(sort: 'Vendor').all
#vendors = #vendors.where(state: params[:state])
end
or better:
def vendors
#vendors = Collective.where(sort: 'Vendor', state: params[:state])
end
Using sessions instead of url params.
This is more or less what you can do, sorry if it is not completly working for your case, just to give an idea.
# view collectives/index (or whatever you have)
<%= form_tag (controller: :collectives, action: :set_status_filter, method: :post) do %>
<%= select_tag(:session_status_filter, options_for_select(#your_list_of_options_for_the_filter)) %>
<%= submit_tag "Set filter" %>
<% end %>
# collectives controller
def index # or whatever, this is the page containing the form and the list to show
#vendors = Collective.where(sort: 'Vendor').all
if session[:session_status_filter] == # etcetera
then #vendors = #vendors.where(state: session[:session_status_filter]) # for example
else # another option just in case, etcetera
end
end
def set_status_filter # this action is called by the form
session[:session_status_filter] = params[:session_status_filter]
respond_to do |format|
format.html { redirect_to *** the view where the form is placed ***, notice: 'the filter is set to: ....' + session[:session_status_filter] } # after the session variable is set the redirects goes to index which uses the session to filter records
end
end
params[:session_status_filter] is passed by the form to collectives#set_status_filter. The value is used to set the session variables. After that the action collectives#set_status_filter redirects to the index, or whatever page you placed the form and the list to show.

Couldn't find Object with 'id'=

stumped here, probably due to my rails noobness.
I am building a 2 sided market place with bids. using devise for 2 user types relevant here, clients and guides. clients build a trip, guides can view trips and then bid on the trip. i've created a custom landing page for the guides (home) once they sign in which lists client trips, i use a custom view and method in my guides controller to do this, no problem.
however, when from that page i try to go to the next custom page for the guide to view the details of the trip (and then submit a bid), suddenly i get a "Couldn't find Trip with 'id'=" error related to the Trip.find(params[:id]) (if i hardcode Trip.find(1) it works).
guides controller
class GuidesController < ApplicationController
def home
#trips = Trip.all
#guide = current_guide
end
def view_trip
#trip = Trip.find(params[:id])
#guide = current_guide
end
end
guide's home page (which is where the guide clicks to view the trip)
<p>Guides's Email: <%= #guide.email %></p>
<% #trips.each do |trip| %>
<li>Location: <%= trip.location.description %></li>
<li>Details <%= trip.details %></li>
<p><%= link_to "View Details and Bid", guides_view_trip_path(trip) %></p>
<% end %>
and then the error output at the page when i try to visit it/click on the link: amazonaws.com/guides/view_trip.1
Couldn't find Trip with 'id'=
Extracted source (around line #21):
19 def view_trip
20
21 #trip = Trip.find(params[:id])
22 ##trip = Trip.find(1)
23 #guide = current_guide
24 end
Request
Parameters:
{"format"=>"1"}
Change this line:
<p><%= link_to "View Details and Bid", guides_view_trip_path(trip) %></p>
By
<p><%= link_to "View Details and Bid", guides_view_trip_path(id: trip.id) %></p>
Your code should be like that
class GuidesController < ApplicationController
def home
#trips = Trip.all
#guide = current_guide
end
def view_trip
#trip = Trip.find(params[:format])
#guide = current_guide
end
end
I don't know what is your routes.rb design, if you need to take this URL with rails default RESTful URL then your routes.rb looks like this
get 'guides/view_trip/:id(.:format)', to: "guides#view_trip", as: :guides_view_trip
#=> guides_view_trip GET /guides/view_trip/:id(.:format) guides#view_trip
Now you can use the view like below
<%= link_to "View Details and Bid", guides_view_trip_path(trip) %>
#=> /guides/view_trip/1
If you use guides_view_trip_path(id: trip.id) then URL looks like this amazonaws.com/guides/view_trip?id=1 and if you use RESTful which I described then looks like this amazonaws.com/guides/view_trip/1
Or you can use Trip.find(params[:id]) to Trip.find(params[:format])
Hope it helps

Search box to find user in rails

I'm somewhat new to rails. I'm going through making the classic twitter clone right now. I want to have a search bar on my homepage that allows the user to search for a twitter handle, and if the handle exists, it will send the user to the show page for that twitter handle.
I've been following a RailsCast on how to implement a simple search, but instead of doing it on the index like the video, I want to do it on the show action. I've run into some problems though. The form sits on my user index view.
Here is the error:
ActionController::UrlGenerationError in Users#index
Showing c:/Sites/Projects/twitterapp/twitter/app/views/users/index.html.erb where line #2 raised:
No route matches {:action=>"show", :controller=>"users"} missing required keys: [:id]
Here is the form:
<%= form_tag(user_path, method: 'get') do %>
<%= text_field_tag(:search, params[:search]) %>
<%= submit_tag("Search", name: nil) %>
<% end %>
Here is my show action:
def show
#user = User.search(params[:search])
end
And here is my search method in my user model:
def self.search(search)
if search
find(:all, conditions:['name LIKE ?', "%#{search}%"])
else
find(:all)
end
end
Actually you cannot use the show method as a search result finder. Because according to the rails convention:
For any resource like users, rails scaffold generates index,new, show, create, update, delete methods based on your routes files.
Thus based on the conventional way, show method always asks for an object. Lets say you are using UserContoller show method. It asks for a user object. Which you haven't provide in the form. that's why :id missing error is given.
I would tell you to do some more learning. And for searching create a different method in a different controller and define that controller method to the routes.rb file. This is the best way to do.
If you still want to use the show method, then change the show methods routing from the routes.rb file. You've to manually declare the show action on routes file.
you are using user_path and path need to inform id from present user
you can do this in action :index but I recommend you to create a action to this
view
<%= form_tag(search_users_path, method: 'get') do %>
<%= text_field_tag(:search, params[:search]) %>
<%= submit_tag("Search", name: nil) %>
<% end %>
routes.rb
resources :users do
post 'search', :on => :collection
end
users_controller.rb
def search
#user = User.search(params[:search])
end
You should to create a view search.html.erb similar as index.html.erb
As Emu and Breno pointed what causing the problem user_path requires an user id
Solution idea:
Why not just point to users index action? like this:
<%= form_tag(users_path, method: 'get') do %>
<%= text_field_tag(:search, params[:search]) %>
<%= submit_tag("Search", name: nil) %>
<% end %>
users_controller.rb:
def index
if params[:search]
#user = User.search(params[:search])
end
end
and you can use ajax remote: true to handle the returned user object
Found your question via Google, but the responses and suggestions didn't work for me. Found another solution that did, so seems worth posting here.
"Search and Filter Rails Models Without Bloating Your Controller":
http://www.justinweiss.com/articles/search-and-filter-rails-models-without-bloating-your-controller/

Nested resource issue

I am struggling to pass an id successfully into my URL for the nested resource I have set up called Jobs.
The error I am getting when I try to pass the #job object into my link is as follows:
No route matches {:action=>"edit", :controller=>"jobs", :user_id=>1, :id=>nil}
Which clearly shows it can't find the id correctly and so is finding nil
At the moment I have my routes setup as so:
resources :users do
resources :jobs
end
and the link I have is <%= link_to "Edit", edit_user_job_path(#user.id,#job) %>
What is interesting is that if I pass the object #jobs with an 's' on the end it will load the page correctly but when I click on the link will try and add all of that users job id's.
In my controller for edit I have:
def edit
#user = current_user
#job = #user.jobs.find(params[:id])
end
Any help really would be much appreciated :)
UPDATE
Okay I was defining the object on the wrong page of my controller (under edit instead of index). The issue I am now having is Couldn't find Job without an ID
I updated my controller index definition to:
def index
#user = current_user
#jobs = #user.jobs.all
#job = #user.jobs.find(params[:id])
end
And have in my view (jobs#index)
<% #jobs.each do |f| %>
...
<%= link_to "Edit", edit_user_job_path(#user.id,job) %>
...
<% end %>
Any advice would be much appreciated if you know where I am going wrong :)
That error means that #job is nil.
The link is to the edit path, and the controller code you've provided is from the edit action in the controller. It seems unlikely that the edit page links to itself.
Look at the code that's actually rendering that page (it will appear in your stack trace) and you'll find that #job is not set. I suspect that you are on the index page and have something like:
<% #jobs.each do |job| %>
...
<%= link_to "Edit", edit_user_job_path(#user.id,#job) %>
...
<% end %>
If that is the case, then the link should be to job, not #job, i.e.
<%= link_to "Edit", edit_user_job_path(#user.id,job) %>
(expanding on iHiD's comment with his own post)
Using the restful resources means that you are going with the rails defaults, which consequently means that the index page gives you a list of all Jobs, and by default no single special job. If you run rake routes from the command line, you get all the routes, with parameters that are set from the URI. It should give you something like this:
user_jobs GET /users/:user_id/jobs(.:format) jobs#index
As you can see, there is no :id (params[:id]) for the index action.

Resources