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
Related
I have this newbie error when i want to upvote a "hack" :
ActionController::ParameterMissing at /hacks/6/upvote
param is missing or the value is empty: vote
With Request parameters exemple :
{"_method"=>"post", "authenticity_token"=>"r+fYieTQDsD6fuonr3oe0YEzkzBXH1S8k6bDENS0wCVr3LEpxGA4mps5saM4RQLvBNDVzsm2zXpGm9TKe3ZIYA==",
"controller"=>"hacks", "action"=>"upvote", "id"=>"6"}
I don't understand why my #vote do not appear in parameters...
Controller hacks_controller.rb
class HacksController < ApplicationController
skip_before_action :authenticate_user!, only: [:upvote]
def upvote
#vote = Vote.new(vote_params)
#hack = Hack.find(params[:id])
# raise
#vote.hack = #hack
if #vote.save
redirect_to root_path
else
p 'Problème de #vote.save !'
end
end
private
def vote_params
params.require(:vote).permit(:hack_id, :user_id)
end
end
Model Vote.rb
class Vote < ApplicationRecord
belongs_to :user
belongs_to :hack
validates :hack, presence: true
end
Thanks !
The Rails strong parameters are meant as mass assignment protection and are not suited to this case.
To create an additional CRUD method properly you can just add the additional route to resources:
resources :hacks do
post :upvote
delete :downvote
end
Note that we are using POST not GET as this is a non-idempotent operation.
You also don't need to pass any parameters. :hacks_id will be present in the path and you should fetch the current user id from the session and not the request parameters.
Passing a user id via the parameters is a really bad practice as its very trivial to spoof by using just the web inspector.
class HacksController < ApplicationController
before_action :set_hack!, except: [:new, :index, :create]
# POST /hacks/:hack_id/upvote
def upvote
#vote = #hack.votes.new(user: current_user)
if #vote.save
redirect_to #hack, success: 'Vote created'
else
redirect_to #hack, error: 'Vote could not be created'
end
end
# DELETE /hacks/:hack_id/downvote
def downvote
#vote = #hack.votes.where(user: current_user).first!
#vote.destroy
redirect_to #vote, success: 'Vote deleted'
end
private
# this will raise ActiveRecord::RecordNotFound if
# the id or hack_id param is not valid. This triggers a 404 response
def set_hack!
if params[:id].present?
Hack.find(params[:id])
else
Hack.find(params[:hack_id])
end
end
end
Then in your view you can create the links / buttons like so:
<% if current_user && #hack.votes.where(user: current_user) %>
<%= button_to 'Downvote', hack_downvote_path(#hack), method: :delete %>
<% else %>
<%= button_to 'Upvote', hack_upvote_path(#hack), method: :post %>
<% end %>
I have a small game in which after the game is over the user is linked to a view that displays a leader board of all users and their scores. To do this I have treated the link as an update action so that the users score can be updated after the game is over, however, upon clicking the link I get an error saying "param is missing or the value is empty: user". I am also wondering if this is being caused because there is no form to be filled simply a variable being updated.
Controllers:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
session[:user_id] = #user.id
redirect_to '/play'
else
render '/'
end
end
def update
#user = User.find(current_user)
if #user.update(user_params)
redirect_to '/leaderboard'
else
render '/play'
end
end
private
def user_params
params.require(:user).permit(:nick_name, :score)
end
end
class ScoresController < ApplicationController
before_action :require_user, only: [:index]
def index
#user = User.find(current_user)
#score = #user.score
#score = 0
end
def leaderboard
#users = User.all
end
end
View-link:
<div class="game-over"><%= link_to 'Game Over', "/update", :style => 'text-decoration:none; color:white;' %></div>
Routes:
Rails.application.routes.draw do
root 'users#new', as: :users
post '/' => 'users#create'
get '/logout' => 'sessions#destroy'
get '/play' => 'scores#index', as: :user
get '/update' => 'users#update'
get '/leaderboard' => 'scores#leaderboard'
user has to be present in the request params because you required it in user_params. You can change link_to to use query parameters as follows:
link_to "Refresh", {controller: 'users', action: 'update', nick_name: "#{user.nick_name}", score: "#{get_score}"}, style: '...'
Or change update route to contain those parameters in the url.
# routes.rb
get '/update/:nick_name/:score' => 'users#update'
Tip: You probably should change it to PUT and use form instead, since update action alters state in the server.
Looks like whatever you are using to pass through your params to make the request is not properly nested under a user key.
I'm using nested routes,I have :booking table and :hotel table
In my routes.rb
resources :hotels do
resources :bookings
end
In my hotel show.html. erb
<%= link_to 'Book Now', new_booking_path(:hotel_id => #hotel.id) %>
In my bookings_controller.rb
def new
#booking = #hotel.bookings.build
end
When the link is clicked, it generates a link
localhost:3000/bookings/new?hotel_id=4
But I still get an error
NoMethodError
Undefined method 'bookings' for nil:NilClass
Extracted source from
def new
#booking = #hotel.bookings.build
end
It appears that you're not retrieving a Hotel object in your new method for your controller. So when you call bookings on the #hotel variable, the nil exception is thrown. It should look something like:
bookings_controller.rb:
def new
#hotel = Hotel.find(params[:hotel_id])
#booking = #hotel.bookings.build
end
Hope it helps!
I think you made a mistake to find #hotel here, Please do this -
In bookings_controller.rb -
def new
#hotel = Hotel.find(params[:hotel_id])
if #hotel.present?
#booking = #hotel.bookings.build
render :new
else
redirect_to root_path
end
end
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
I've been following step by step example for wicked gem https://github.com/schneems/wicked/wiki/Building-Partial-Objects-Step-by-Step but I'm struggling to make it work
routes.rb
post '/trips/building/build(.:format)', :to => "trips/build#create"
resources :trips do
resources :build, controller: 'trips/build'
end
trips_controller.rb
class TripsController < ApplicationController
include Wicked::Wizard
before_action :set_trip, only: [:show, :update]
steps :basic, :details
def show
render_wizard
end
def create
#trip = Trip.create
redirect_to wizard_path(steps.first, :trip_id => #trip.id
end
def update
#trip.update_attributes(trip_params)
render_wizard #trip
end
private
def set_trip
#trip = Trip.find(params[:trip_id])
end
def trip_params
....
end
end
index.html.erb
<%= link_to 'Create New Trip', '/trips/building/build', :method => :post, :class=>'btn btn-danger'%>
error in console:
Started POST "/trips/building/build" for 127.0.0.1 at 2014-04-16 22:50:20 -0700
ActionController::RoutingError - uninitialized constant Trips
this is driving me crazy...
any thoughts?
Your controller is named incorrectly - your route is pointing to the Trips::BuildController but your controller is defined as the TripsController.
The link you shared defines a Products::BuildController so that's why it works there.