How do I add an additional resource action to my routes? - ruby-on-rails

I have a resource named Volunteers:
class VolunteersController < ApplicationController
before_filter :authenticate_user!
def index
##volunteers = Volunteer.all()
#volunteers = Volunteer.paginate(:page => params[:page])
end
def show
#volunteer = Volunteer.find(params[:id])
end
def new
#volunteer = Volunteer.new
end
def create
#post = Volunteer.new(volunteer_params)
#post.save
redirect_to #post
end
def destroy
#volunteer = Volunteer.find(params[:id])
#volunteer.destroy
redirect_to :action => 'index'
end
def search
#volunteers = Volunteer.search params[:search]
end
private
def volunteer_params
params.require(:volunteer).permit(:forename, :surname)
end
end
I have added an additional action called search but I'm having issues mapping it in my routes file:
root 'home#index'
resources :volunteers
How do I map to the search action (including params)?

There is an example in the route file itself:
# Example resource route with options:
# resources :products do
# member do
# get 'short'
# post 'toggle'
# end
#
# collection do
# get 'sold'
# end
# end
You need to add the search method as a post (or whatever is appropriate) option for the resource, you can either add it to collection or member - collection methods won't look for a specific item id in the url, which is appropriate for a search method.
resources :volunteers do
collection do
post :search
end
end

Related

Why am I getting a recordnotfound error when trying to access an instance in rails?

I have a user profile controller called "userinfo" and it's corresponding view. The userinfo index is the root path. In the homepage(which is the userinfo index), I have a link that takes you to the user profile page. It is giving me this error when I go to the home page:
My routes are:
My userinfos_controller:
class UserinfosController < ApplicationController
before_action :find_userinfo, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
def index
#userinfors = Userinfo.find(params[:id])
end
def show
#myvideo = Video.last
end
def new
#userinformation = current_user.userinfos.build
end
def create
#userinformation = current_user.userinfos.build(userinfo_params)
if #userinformation.save
redirect_to root_path
else
render 'new'
end
end
def edit
end
def update
end
def destroy
#userinformation.destroy
redirect_to userinfo_path
end
private
def userinfo_params
params.require(:userinfo).permit(:name, :email, :college, :gpa, :major)
end
def find_userinfo
#userinformation = Userinfo.find(params[:id])
end
end
and my view is:
<%= link_to 'profile', userinfors_path(#userinfors) %>
My routes.rb file:
Rails.application.routes.draw do
devise_for :users
resources :userinfos do
resources :videos
end
resources :pages
get '/application/decide' => 'application#decide'
root 'userinfos#index'
get '/userinfos/:id', to: 'userinfos#show', as: 'userinfors'
end
Thanks for any help!
ok, there are multiple errors and you are not following conventions of rails, index is not for what you have used.
Index is used to list all the users and show for a particular one with id passed in params.
Your index path is, as you can see, /userinfos which is correct and it doesn't have any id with it but you are trying to find user with params[:id] which is nil and hence the error.
Lets try out this:
def index
#userinfors = Userinfo.all #pagination is recommended
end
In your index view,
<% #userinfors.each do |userinfor| %>
<%= link_to "#{userinfor.name}'s profile", userinfo_path(userinfor) %>
<% end %>
It should work now.
Please read routing and action controller to get the idea and understand the magic behind rails routing and mvc architecture..

I'm getting error "uninitialized constant SongsController" on ruby on rails

I'm getting an error like that, I'm new in rails.
my routes.rb
Rails.application.routes.draw do
get 'welcome' => 'page#search'
resources :songs
end
search.html.erb
<%=form_for #song do |f|%>
<%=f.text_field :search%>
<%=f.submit 'Search'%>
<%end%>
page_controller.rb
class PageController < ApplicationController
attr_accessor :a
def search
#songs = Song.all
#song = Song.new
end
def new
#song = Song.new
end
def Create
#song = Song.new()
if #song.save
rediect_to ''
else
render new
end
end
def parameter
params.require(#song)
end
end
path
welcome_path GET /welcome(.:format) page#search
song_new_path POST /song/new(.:format) song#new
songs_path GET /songs(.:format) songs#index
POST /songs(.:format) songs#create
new_song_path GET /songs/new(.:format) songs#new
edit_song_path GET /songs/:id/edit(.:format) songs#edit
song_path GET /songs/:id(.:format) songs#show
PATCH /songs/:id(.:format) songs#update
PUT /songs/:id(.:format) songs#update
DELETE /songs/:id(.:format) songs#destroy
you declared resources :songs in your routes file, so Rails expecte SongsController inheriting from ApplicationController in your app/controllers folder. If you do not have this controller, create new file:
app/controller/songs_controller.rb
class SongsController < ApplicationController
# add implementation of CRUD methods
def index
end
def show
end
def new
end
# ...
end
Rename your controller as SongsController

Devise edit user not working after using custom registrations controller

it might be a silly question but I am stuck with this for some time as I am new to rails.
I am basically using a custom registration controller to overwrite devise
class RegistrationsController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
# GET /Users
def index
#Users = User.all
end
# GET /Users/1
def show
end
# GET /Users/new
def new
#User = User.new
#course = Course.find_by id: params["course_id"]
end
# POST /Users
def create
#User = User.new(user_params)
if #User.save
redirect_to #User.paypal_url(registration_path(#User))
else
render :new
end
end
protect_from_forgery except: [:hook]
def hook
params.permit! # Permit all Paypal input params
status = params[:payment_status]
if status == "Completed"
#User = User.find params[:invoice]
#User.update_attributes notification_params: params, status: status, transaction_id: params[:txn_id], purchased_at: Time.now
end
render nothing: true
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#User = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params.require(:user).permit(:course_id, :name, :email, :password,:password_confirmation)
end
end
In my routes I have
devise_for :users ,:controllers => { :registrations => "registrations" }
So now I have
edit_user_registration_path GET /users/edit(.:format) registrations#edit
My question is how can I route only edit back to devise/registrations/edit or what can i add to my registrations controller so that I get something similar?
If you want to delegate the create action of the registrations controller to Devise, I recommend you to create a controller that inherits from the Devise one:
class RegistrationsController < Devise::RegistrationsController
def create
super #We call super because we don't want to override this action
end
def edit
#Custom code to override this action
end
end
Your route's configuration stays as it is, you just have to change your controller, you may also want to know that it's possible to ADD functionality to what devise already does, instead of override it:
def edit
super do |resource|
#Here you add what you'll do AFTER devise works
end
end

How to nest collection routes?

I use the following routes configuration in a Rails 3 application.
# config/routes.rb
MyApp::Application.routes.draw do
resources :products do
get 'statistics', on: :collection, controller: "statistics", action: "index"
end
end
The StatisticController has two simple methods:
# app/controllers/statistics_controller.rb
class StatisticsController < ApplicationController
def index
#statistics = Statistic.chronologic
render json: #statistics
end
def latest
#statistic = Statistic.latest
render json: #statistic
end
end
This generates the URL /products/statistics which is successfully handled by the StatisticsController.
How can I define a route which leads to the following URL: /products/statistics/latest?
Optional: I tried to put the working definition into a concern but it fails with the error message:
undefined method 'concern' for #<ActionDispatch::Routing::Mapper ...
I think you can do it by two ways.
method 1:
resources :products do
get 'statistics', on: :collection, controller: "statistics", action: "index"
get 'statistics/latest', on: :collection, controller: "statistics", action: "latest"
end
method 2, if you have many routes in products, you should use it for better organized routes:
# config/routes.rb
MyApp::Application.routes.draw do
namespace :products do
resources 'statistics', only: ['index'] do
collection do
get 'latest'
end
end
end
end
and put your StatisticsController in a namespace:
# app/controllers/products/statistics_controller.rb
class Products::StatisticsController < ApplicationController
def index
#statistics = Statistic.chronologic
render json: #statistics
end
def latest
#statistic = Statistic.latest
render json: #statistic
end
end

NoMethodError in controller#new - undefined method

I'm getting a NoMethodError in the new action of my business_controller.
It seems to be acessing the #business object for a form in my view and the error occurs then:
undefined method `businesses_path' for
Here is my new method:
def new
if Business.where(:user_id => current_user.id).first.blank?
#business = Business.new
else
redirect_to user_businesses_path(current_user.id)
end
end
My routes are:
resources :users do
resources :businesses
member do
get 'account'
post 'payment'
put 'update_password'
get 'membership'
end
end
mind.blank's suggested changes
before_filter :check_if_user_has_business, :only => :index
def new
#business = Business.new
end
private
def check_if_user_has_business
redirect_to new_user_business_path(current_user) unless current_user.business
end
Do you have a route businesses_path or only user_businesses_path? If you only have the second one then you should specify that URL in your form:
<%= form_for #business, url: user_businesses_path do |f| %>
Also, if you have the correct associations set up, then you can write your if statement as follows:
if current_user.business.nil? # since it's a has_one association
Here's how I would write it:
Class BusinessesController < ApplicationController
before_filter :check_if_user_has_business, only: :new
def new
#business = Business.new
end
private
def check_if_user_has_business
redirect_to user_businesses_path(current_user) if current_user.business
end
end

Resources