Rails 4 link_to No route matches - link-to-function

I get the error No route matches {:action=>"index", :controller=>"search"}
When using
link_to "Next Page", {:controller => 'search', :action => 'index'}
My routes.rb contains
resources :search, only: [:index]
The action works fine when I use
link_to "Next Page", '/search'
Rake routes result
Prefix Verb URI Pattern Controller#Action
errors_cookie GET /errors/cookie(.:format) errors#cookie
GET /categories(/:level1)(/:level2)(/:level3)(.:format) search#categories
GET /category/filter/:type(.:format) search#category_filter_sort
brand GET /brand(.:format) search#brand
GET /brand/filter/:type(.:format) search#brand_filter_sort
search_index GET /search(.:format) search#index
search_suggest GET /search/suggest(.:format) search#suggest
search_list GET /search/list(.:format) search#list
GET /search/filter/:type(.:format) search#filter_sort
GET /sd/:slug(.:format) search#show
GET /sd/compare/:id(.:format) search#compare
delete_favourites POST /favourites/delete(.:format) favourites#delete
usuals_favourites GET /favourites/usuals(.:format) favourites#usuals
orders_favourites GET /favourites/orders(.:format) favourites#orders
favourites GET /favourites(.:format) favourites#index
POST /favourites(.:format) favourites#create
Routes for Spree::Core::Engine:
spree_user_omniauth_authorize GET|POST /users/auth/:provider(.:format) spree/omniauth_callbacks#passthru {:provider=>/facebook|twitter|github|google_oauth2|amazon/}
spree_user_omniauth_callback GET|POST /users/auth/:action/callback(.:format) spree/omniauth_callbacks#:action
Routes for Ahoy::Engine:
visits POST /visits(.:format) ahoy/visits#create
events POST /events(.:format) ahoy/events#create

Its a spree app and the controller was inherited from Spree::BaseController.
url_for only sees routes within the spree engine and not globals
Fixed the issue by adding main_app to url_for main_app.url_for(...)
Used this monkey patch for kaminari
Thanks for your time Alexander.

Related

How to make a Haml form with two conditional actions

On submit this form will call the put action on the controller:
.panel-body{style: 'background:#0E0D0D;'}
=form_for #payment, method: :put, html: {id: 'edit_bank_detail'} do |f| .row.text_white
.form-group.col-lg-12
=f.label :paypal_email_address
=f.email_field 'user_paypal_email',class: 'form-control'
.row.text-center
.form-group.col-lg-12
=f.submit 'Submit', class: 'btn btn-primary text_black',data: { disable_with: "Please wait..." }
I need it to call the put or create action based on the condition:
if #payments.new_record?
# create action
else
# put action
You don't even need to specify the HTTP method in the first place. form_for and its successor form_with are smart enough to figure out both the path for the action attribute and the method by calling #persisted? on the #payment model instance that you pass as the first argument.
= form_for #payment, html: {id: 'edit_bank_detail'} do |f|
Given conventional routes this will point the form to POST /payments or PATCH /payments/:id if the record has been persisted. Rails has used PATCH instead of PUT for updates since 2012 but resources and resource still generate additional PUT routes for backwards compatibility.
I tried something like this and it works.
=f.submit 'Submit', action_name: #return.new_record? ? 'create' : 'update'
Thanks #Sebastian Palma followed your suggestion.

html slim link_to undefined method error

In my rails project, I ran rake routes and got the following output:
Prefix Verb URI Pattern Controller#Action
obelisk_callflow_nodes GET /obelisk/callflows/:callflow_id/nodes(.:format) obelisk/nodes#index
POST /obelisk/callflows/:callflow_id/nodes(.:format) obelisk/nodes#create
new_obelisk_callflow_node GET /obelisk/callflows/:callflow_id/nodes/new(.:format) obelisk/nodes#new
edit_obelisk_callflow_node GET /obelisk/callflows/:callflow_id/nodes/:id/edit(.:format) obelisk/nodes#edit
obelisk_callflow_node GET /obelisk/callflows/:callflow_id/nodes/:id(.:format) obelisk/nodes#show
PATCH /obelisk/callflows/:callflow_id/nodes/:id(.:format) obelisk/nodes#update
PUT /obelisk/callflows/:callflow_id/nodes/:id(.:format) obelisk/nodes#update
DELETE /obelisk/callflows/:callflow_id/nodes/:id(.:format) obelisk/nodes#destroy
obelisk_callflows GET /obelisk/callflows(.:format) obelisk/callflows#index
POST /obelisk/callflows(.:format) obelisk/callflows#create
new_obelisk_callflow GET /obelisk/callflows/new(.:format) obelisk/callflows#new
edit_obelisk_callflow GET /obelisk/callflows/:id/edit(.:format) obelisk/callflows#edit
obelisk_callflow GET /obelisk/callflows/:id(.:format) obelisk/callflows#show
PATCH /obelisk/callflows/:id(.:format) obelisk/callflows#update
PUT /obelisk/callflows/:id(.:format) obelisk/callflows#update
DELETE /obelisk/callflows/:id(.:format) obelisk/callflows#destroy
I have a html.slim file for showing all the callflows (i.e.obelisk/nodes#index). In this file, I want to add a button to show the nodes of each callflow (i.e. connect that button to obelisk_callflow_nodes GET /obelisk/callflows/:callflow_id/nodes)
I've tried = link_to 'Nodes', obelisk_callflow_nodes_path(callflow_id: c.id), method: :get, class: 'btn btn-primary' where c is a callflow object. I've checked that c is what I want because I have c.name rendering properly. However, I'm getting the following error:
undefined methodobelisk_callflow_nodes_path' for #<#:0x00007fb3d5abebc8>`
I've checked that I do have an index method for my Obelisk::NodesController
I changed the routes so that I no longer user namespace obelisk so the routes don't start with /obelisk/. This fixes the problem. I know it might not be the best solution but in this case it has worked for the purpose of my project.

.collect method get an error undefined method `collect' for nil:NilClass

I'm trying to have a drop down list but when i try it it give me
undefined method `collect' for nil:NilClass
the controller:
def existing
#courses = Course.all
end
def duplicate
course = Course.find_by_id(permitd_up[:id])
new_course = course.dup
if new_course.save
redirect_to :action => 'show'
else
redirect_to :back
end
end
the view:
<h3>Choose a Course</h3>
<%= form_for :course , url: {:action => "duplicate" , method: "post"} do |f|%>
<%= f.select :id , #courses.collect{|c| [c.id , c.name]} %>
<br><br>
<%= f.submit%>
<%end%>
You will receive the following error
undefined method `collect' for nil:NilClass
on
<%= f.select :id , #courses.collect{|c| [c.id , c.name]} %>
Only when #courses instance variable was not set in the action that rendered this particular view.
I see that #courses variable is set in the existing method. If you are using existing as an action which renders this view then your view name must be existing.html.erb.
Or if you are rendering the view from a different action then in that case you should set #courses value in that particular action by either directly setting the value within action OR by calling existing method from there.
If you have your courses as a database table, you might want to try using rails' built in field helper collection_select. It will populate your select field with all of the data available in your model. If you want a drop-down like the one you are describing, I believe using collection select is the best way to handle it.
You can read up on it here: http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html
Alternatively, if you have a ton of courses, maybe try looking into using a text field with autocomplete. Jquery UI has a plugin that makes this very easy. You can check out the railscasts for it here: http://railscasts.com/episodes/102-auto-complete-association-revised.
It requires a pro account but if you do a lot of rails developing it will be the best $9 you spend every month.
If you would like to continue to do it this way, make sure that you are defining
#courses = Courses(:all) in the correct controller action, otherwise you will have nothing to render.

Making AJAX requests in Rails without a form

So I have a posts scaffold generated in a Rails app and I've added an upvote and downvote column to the post model. I added an "upvote" button on the view file and I need to make an AJAX call and query the database when you hit the upvote button, but the upvote button has no real Rails <form> attached to it. How can I make this AJAX call and add the upvote to the database for the upvoted post?
When I make this AJAX call:
$('.up,.down').click(function(){
$.ajax({
type: 'POST',
url: '/posts',
dataType: 'JSON',
data: {
post: {
upvote: 1
}
},
success: function(){
alert('success')
}
});
});
It returns a 500 error. Where do I go form here?
You could use the :remote => true attribute on the link_to helper
for example:
<%= link_to post_upvote_path(post), :remote => true, :method => "put" %>
<%= link_to post_downvote_path(post), :remote => true, :method => "put" %>
then in config/routes.rb:
resources :posts do
put "upvote", :to => "posts#upvote", as: :upvote
put "downvote", :to => "posts#downvote", as: :downvote
end
then handle the voting in your posts controller, like you probably already are and grab the post id with params[:id] in the action
Here is an intro to rails flavored unobtrusive javascript
Update
To see the upvote and downvote routes that were created, go to the terminal and type
rake routes | grep vote
this will give you a list of all of your routes that have "vote" in the name. Or just type rake routes to get a list of all of them. The first column is the named route, just append '_path' to the end of it to use it in your app - like post_upvote_path above would be seen as
post_upvote PUT /posts/:id/upvote(.:format) posts#upvote
And in you PostsController you would want these actions:
class PostsController < ApplicationController
###
# index, show... other RESTful actions here
###
def upvote
#post = Post.find params[:id]
# code for however you are voting up the post here
end
def downvote
#post = Post.find params[:id]
# code for however you are voting down the post here
end
end

add comparison feature in rails

i'm having a bit of trouble with adding a certain feature. i'm working on a buy/sell site and i want to be able to compare posts. here's what i have so far:
in the posts view:
<%= button_to "Add to Compare", :action => "addCompare" %>
in the corresponding controller:
##a = Array.new()
def addCompare
##a << Post.id
end
so, all i want to do is add the post's id to the array ##a. when i test this, i click on the "Add to Compare" button and I'm welcomed with this:
Template is missing
Missing template posts/addCompare with {:locale=>[:en, :en], :formats=>[:html], :handlers=>[:rxml, :rjs, :builder, :rhtml, :erb]} in view paths "/home/mja32/470repo/traders/app/views", "/var/lib/gems/1.8/gems/devise-1.4.2/app/views"
So I guess it's trying to redirect to a view. How do I prevent it from doing this? All I want this button to do is to add the post's id to the array and nothing more.
Thanks in advance,
Matt
First of all, storing persistent data in a controller's class variable isn't going to work the way you want it to. There's no guarantee that ##a will be the same array on your next addCompare call; for example, your next addCompare call could be handled by a different process. Also, what happens if two different clients call addCompare? Do you really want to mix their data together in one pile? Probably not. Your first task is to replace ##a with a real per-user persistent store.
If you want to return nothing at all from your controller, just do this at the end of your controller method:
render :nothing => true, :status => :ok
That will tell Rails that something has already been rendered so it doesn't need to try the default rendering action (which is to render the posts/addCompare view) and returns nothing more than a 200 status code to the client.
Once that's in place, you'll probably want to AJAXify your button with :remote => true:
:remote - If set to true, will allow the Unobtrusive JavaScript drivers to control the submit behaviour. By default this behaviour is an ajax submit.
So this:
<%= button_to "Add to Compare", { :action => "addCompare" }, { :remote => true } %>
Note that button_to looks like this:
button_to(name, options = {}, html_options = {})
and that :action is for options but :remote is for html_options so you have to explicitly set up the hashes with {}; you could just wrap the options in braces:
<%= button_to "Add to Compare", { :action => "addCompare" }, :remote => true %>
but I prefer the consistency of wrapping them both by hand.