ActionController::UrlGenerationError in Univ#index - ruby-on-rails

I tried to list out the values of a specific table in the database using the following view file
index.html.erb
<%= form_tag univ_path, method: :get do %>
<p>
<%= text_field_tag :query, params[:query] %>
<%= submit_tag "Search", name: nil %>
</p>
<% end %>
<h1>List of Universities based on ranking</h1>
<div id="articles">
<% #univ.each do |univ| %>
<h2>
<%= link_to univ.univ_name, univ %>
</h2>
<div class="info">
<b>Location:</b> <%= univ.location %>, <%= univ.state %> <br/>
</div>
<br /><br />
<div class="content"><p><%= univ.description %><p></div>
<% end %>
</div>
and the controller file is as follows
univ_controller.rb
class UnivController < ApplicationController
def index
if params[:query].present?
#univ= Univ.search(params[:query])
else
#univ=Univ.all
end
end
def show
#univ= Univ.find(params[:id])
end
def register
#univ = Univ.new(params[:univ])
if(request.post? and #univ.save)
flash[:notice]= "Account Created Successfully"
redirect_to :controller => 'univ', :action => 'register'
end
end
end
I was able to list out the contents of the table from db. However, when I include the form_tag for implementing search it results an error
No route matches {:action=>"show", :controller=>"univ"} missing required keys: [:id]
my routes.rb has
resources :univ get 'search' => "univ#index", :as => "search"
Please suggest necessary changes

Change the form_for in index.html.erb as below:
<%= form_tag search_path, method: :get do %>
I suppose you intended to submit the form on index action using the search route defined as:
get 'search' => "univ#index", :as => "search"
for that you would have to submit the form on search_path.
You are getting the error as No route matches {:action=>"show", :controller=>"univ"} missing required keys: [:id] because currently you are submitting the form on univ_path which would route to show action and therefore require an id.

I just had this problem with a project I'm working on, and it turned out to be a Nil field in my database. Are you saving data to ruby sqlite? Check for a record that has a nil [:id] and delete that record using Model.destroy(id) and you should be able to render the page again

Related

Missing required keys: [:id] - Routing to a view for each instance of my model with its unique ID

I'm working on a job board to learn/practice rails. I have a separate view for each job category, and I want the user to be able to click on a particular job posting to access another view with all of the listing's details. I've partially figured out the routing, as I'm able to go to localhost:3000/jobs/listing/7 for example to see the view for the listing of id:7. I'm having a problem linking to the /listing/:id from my job category view, and can only access a view for a specific id by typing it into the address bar. I've been working on this for days and checked out many related questions on here, but can't seem to figure it out. I believe I'm overlooking a simple, but critical detail, since i'm not very experienced with rails.
Here is my job category view:
<div class="cat-banner" id="developer">
<h1>Human Resources Jobs</h1>
<h4 class="listing-count"><%= Job.where(:category => 'Human Resources').count.to_s + ' Listings' %></h4>
</div>
<div class="category-page">
<!-- Full-Stack Developer Jobs -->
<div class="jobs-posted">
<hr class="other-line">
<% if Job.where(:category => 'Human Resources').count > 0 %>
<% #jobs.each do |job| %>
<div class="job">
<% if job.category == "Human Resources" %>
<span class="job-logo"><%= image_tag('salesforce.png', :size => "60x40") %></span>
<span id="line-align"><p class="title"><%= link_to job.title, listing_path(#job) %> </p>
<p class="name"><%= job.name %></p></span>
<% if job.location == "Remote" %>
<span class="remote-tag"><%= job.location.upcase %></span>
<% else %>
<p class="location"><%= job.location %></p>
<% end %>
<p class="kind"><%= job.kind %></p>
<p class="time-stamp"><%= job.created_at.strftime("%A, %B %d %Y") %></p>
<hr class="line">
<% end %>
</div>
<% end %>
<% else %>
<p>There are no human resources jobs at the moment...</p>
<p style="text-decoration: underline;"><%= link_to 'Post a Human Resources Job Here', new_job_path %></p>
<% end %>
</div>
<!-- End of Human Resources Jobs -->
</div>
And my routes.rb file:
Rails.application.routes.draw do
get 'subscribers' => 'subscribers#index'
get 'jobs/remote' => 'jobs#remote'
get 'jobs/listing/:id' => 'jobs#listing', as: 'listing'
get 'jobs/company' => 'jobs#company'
get 'jobs/dev' => 'jobs#dev'
get 'jobs/design' => 'jobs#design'
get 'jobs/marketing' => 'jobs#marketing'
get 'jobs/ai' => 'jobs#ai'
get 'jobs/fullstack' => 'jobs#fullstack'
get 'jobs/frontend' => 'jobs#frontend'
get 'jobs/backend' => 'jobs#backend'
get 'jobs/it' => 'jobs#it'
get 'jobs/software' => 'jobs#software'
get 'jobs/product' => 'jobs#product'
get 'jobs/cloud' => 'jobs#cloud'
get 'jobs/mobile' => 'jobs#mobile'
get 'jobs/database' => 'jobs#database'
get 'jobs/datascience' => 'jobs#datascience'
get 'jobs/blockchain' => 'jobs#blockchain'
get 'jobs/security' => 'jobs#security'
get 'jobs/support' => 'jobs#support'
get 'jobs/network' => 'jobs#network'
get 'jobs/finance' => 'jobs#finance'
get 'jobs/sales' => 'jobs#sales'
get 'jobs/hr' => 'jobs#hr'
get 'jobs/businessdev' => 'jobs#businessdev'
resources :jobs
root 'jobs#index'
get 'jobs/index'
get 'jobs/new'
And part of the Jobs Controller:
class JobsController < ApplicationController
def index
#jobs = Job.all
#subscribers = Subscriber.all
end
def new
#job = Job.new
end
def listing
#job = Job.find(params[:id])
end
def show
#job = Job.find(params[:id])
end
def create
#job = Job.new(params.require(:job).permit(:title, :url, :category, :kind, :location, :description, :name, :summary, :website, :email, :companyDescription, :headquarters ))
if #job.save
redirect_to root_path
else
render "new"
end
respond_to :html, :json
end
I've tried:
<%= link_to job.title, listing_path(#job) %>
<%= link_to job.title, listing_path(#job.id) %>
<%= link_to job.title, listing_path(#job[:id]) %>
<%= link_to job.title, listing_path %>
and other variations that I thought would work from reading StackOverflow
I believe my problem comes from this link_to statement (wrong syntax?), as everything looks alright in my jobs controller and routes file.
I either get:
No route matches {:action=>"listing", :controller=>"jobs", :id=>nil}, missing required keys: [:id],
or
undefined method `id' for nil:NilClass,
or
undefined method `[]' for nil:NilClass
The "missing required keys: [:id]" error is confusing me. I've checked out many resources trying to figure out how to pass the :id but can't solve it.
This is my first post on here and I REALLY appreciate any help and look forward to being knowledgeable enough in the future so I can answer questions too.
rake routes
The view that you are putting as example is using the instance variable #jobs. According with your controller that would be your index action where you don't have #job defined
Note: Notice on that view you are using #jobs and job on your iterator
So I think if you change #job for job that would fix the problem on that view
<%= link_to job.title, listing_path(job) %>
As the error clearly states, your path is expecting a job id but it is not getting one, so inspecting your call for the path, in line:
<span id="line-align"><p class="title"><%= link_to job.title, listing_path(#job) %> </p>
you are passing #job as param to the listing path.
change it to job so it would be:
<span id="line-align"><p class="title"><%= link_to job.title, listing_path(job) %> </p>
For the missing id, you should do:
<%= link_to job.title, listing_path(id: #job) %>
since your id is stored in the variable #job
It seems that the reason this isn't working is because you are not sending the correct argument to your link_to here:
<%= link_to job.title, listing_path(#job) %>
You have to remember that you are iterating through all your #jobs and calling each individual job with the job variable between the | |. You are trying to create a link to each individual job, so the correct link_to should be:
<%= link_to job.title, listing_path(job) %>
Where job is the individual job that the link_to is looking for.

Rails 5. How to submit from the form_tag to custom action?

I'm a real newbie at Ruby and Rails, and I've been looking for the solution for two days. I need to submit data from form_tag to action 'create' in my controller to add new entries to database, but looks like I'm doing something terribly wrong, because absolutely nothing happens, and it seems that form_tag doesn't even redirect to needed action.
Here's the page code:
<h1>Todos</h1>
<% #projects.each do |project| %>
<tr>
<h2><%= project.title %></h2>
<% project.todos.each do |todo| %>
<ul style="list-style-type:disc">
<li><%= todo.text %></li>
</ul>
<% end %>
</tr>
<% end %>
<%= form_tag({controller: "mega", action: "create"}, method: "get", remote: true) do %>
<h2>New todo</h2>
<p>
<%= text_field_tag 'text' %>
</p>
<p>
<%= select_tag 'title', options_from_collection_for_select(#projects, 'id', 'title') %>
</p>
<p>
<%= link_to 'CANCEL' %>
<%= link_to 'OK', "", :onclick => "$('#form_id').submit()" %>
</p>
<% end %>
And the controller:
class MegaController < ApplicationController
def index
#projects = Project.all
#todos = Todo.all
end
def update
end
def create
#newTodo = Todo.create(text: params[:text])
#newProject = Project.find_by(title: params[:title])
#newProject.todos << #todo
#newTodo.save
end
end
My routes file. I seriously don't know how it works:
Rails.application.routes.draw do
get 'mega/index'
root 'mega#index'
get 'mega/update'
post 'mega/create'
resources :todos
resources :projects
end
You create resources with a POST request. Never GET.
GET requests should be idempotent - they should not update or alter resources on the server. One very important reason is that they are stored in the browser's history, so pressing the back button will cause unintended consequences for the user.
In Rails flavor MVC instead of tacking the action name on the path of the route you use the HTTP verb to create routes to the correct action:
GET /things things#index
POST /things things#create
I'm not going to attempt to salvage your code (it's deeply flawed) and instead show you how you would solve this the rails way as it is much simpler:
<%= form_for(Todo.new) do |f| %>
<h2>New todo</h2>
<%= f.text_field :text %>
<%= f.collection_select(:project_id, #projects, :id, :title, prompt: true) %>
<%= f.submit %>
<% end %>
This would submit to todos#create - if you want to route it to an unconventional action you can use the url option:
<%= form_for(Todo.new, url: polymorphic_path(controller: 'foo', action: 'bar')) do |f| %>
It's best to learn the rules before you break them.

Search on Welcome Controller

I have a Product (imovel) controller where the users can create his own Products (imovels). I am using devise for the authentication and the CRUD (create, Update, Delete) needs login. So for the clients be able to see the products and doesn't need a user, I created the Welcome controller where so it is the root.
In the Index of the Products I use Ransack to do the research in the table and works just fine. (very happy about it).
On the welcome controller I try to do the same thing, but when I submit the search the page gets redirect to the imovels#index.
Controller:
class WelcomeController < ApplicationController
def index
#q = Imovel.ransack(params[:q])
#imovel = #q.result(distinct: true)
end
end
View:
<div class="container text-center">
<%= search_form_for #q do |f| %>
# Search if the name field contains...
<%= f.label :descricao_cont %>
<%= f.search_field :descricao_cont %>
<%= f.submit "Pesquisar", class: "btn btn-primary" %>
<% end %>
</div>
Another thing that can be important in the index (imovels#index) there is a for in a tr and the information is filtered there:
Imovels Index
<tbody>
<% #imovels.each do |imovel| %>
<tr>
<td><%= imovel.id %></td>
<td><%= imovel.descricao %></td>
<% end %>
And in the welcome controller where I need the search, I used Divs:
Welcome Index
<% #imovels.each do |imovel| %>
<div class="card">
<div class="containerImovel">
<h4><b><%= imovel.descricao %></b></h4>
<p><%= imovel.cidade %> - <%= imovel.bairro.nome %> </p>
</div>
</div>
<% end %>
How can I do the search on the divs of welcome controller? Ransack is the better option for it? It is possible to search in the has_many :through association?
Add a path for it in your routes.rb
resources :imovel do
collection do
match 'search' => 'welcome#search', via: [:get, :post], as: :search
end
end
and then add a new controller action to WelcomeController
def search
index
render :index
end
and afterwards modify the search form like so
<%= search_form_for #q, url: search_imovel_path, html: { method: :post } do |f| %>
Be sure to recheck the naming/variables as I'm not completely familiar with your app

How HTTP method works in a form_tag helper?

I tried to set up a form which I wanted it to move to members#index.
But with the code①, I failed and the form moved to members#show.
☆code①
<%= form_tag :action => 'index' do %>
<div class = "field">
<%= label_tag 'place', '活動場所:' %><br />
<%= text_field_tag 'place' %>
</div>
<%= submit_tag '検索' %>
<% end %>
And I got some advice and fixed the code②.
I have a question. Why did I have to change the method from "post" to "get"?
☆code2
<div class= "form_index">
<%= form_tag({:action=>"index"}, {:method=>"get"}) do %>
<div class="from_field_index">
<%= label_tag 'place', '場所:' %>
<%= text_field_tag 'place' %>
</div>
<div class="search_button">
<%= submit_tag '検索' %>
<% end %>
</div>
</div>
☆members_controller
def index
if params[:place].present?
#members = Member.where("place like ?" , "%" + params[:place] + "%")
else
#members = Member.all
end
respond_to do |format|
format.html # index.html.erb
format.json
end
end
GET implies to retrieve something from server. POST implies to add something to server.
Search will get some results from server, so the conventional way is to use GET on this action. Search form is the perfect example of form using GET.
Also, your controller action index responds to 'GET' only, defined by default resource route. It also need the request sent by your client side to be 'GET'.
Another benefit of using GET on search is, the params will be in url so the url is bookmarkable, shareable and history nagivatable. Think about Google, you can share a search result by just copying the link.

Rails : No route matches , creating contact us form

I am making a contact us form that doens't have any model. I just want it to be a popup in the home page when people click on contact us.
In the partial we load _contact.html.haml , this is what we have
<div class="contact-us-form">
<h>Contact Us</h>
<% form_tag(:controller => "application", :action => "deliver_contact_form", :method=>'post') do %>
<p>
<%= label_tag(:contact_email, "Your Email") %>
</p>
<p>
<%= text_field_tag(:contact_email) %>
</p>
<p>
<%= label_tag(:contact_detail, "Details") %>
</p>
<p>
<%= text_area_tag(:contact_detail,:"", :size=> "44x6") %>
</p>
<p>
<%= submit_tag("Submit") %>
</p>
<% end %>
<div id="contact_cancel"><%= link_to "Cancel", "javascript:void()"%></div>
</div>
and we define the action deliver_contact_form as this in application_controller.rb
def deliver_contact_form
ContactMailer.welcome_email(params).deliver
respond_to do |format|
format.html { redirect_to comments_path }
end
end
when I run just the home page (localhost:3000) I get
No route matches {:controller=>"application", :action=>"deliver_contact_form", :method=>"post", :locale=>:en}
I was wondering what I need to do?
Thanks,
mina
You need to define the route in your routes.rb
I also suggest creating a new controller, even for a small action like this, anyway:
match '/deliver_contact_form' => 'application#deliver_contact_form', :via => :post
<% form_tag(deliver_contact_form_path, :method => 'post') do

Resources