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.
Related
I want to allow Users to have two edit pages, one which is the default Devise page that requires a password and the other edit page which allows them to edit some parts of their profile without a password.
I have seen their guide pages like this which allows them to edit their profile without providing a password. However I want to have both options available to the user instead of just one.
How would I go about doing this?
My Attempt
I have tried to create my own update route in the Users controller which will solve the problem but this creates a problem when a User resets their password as it gets routed to the User#update which will cause an error as there is no User available during the password reset in Devise.
class UsersController < ApplicationController
before_action :authenticate_user!, :only => [:crop] #:edit , :update
def show
#user = User.find(params[:id])
authorize #user
end
def update
#user = User.find(params[:id])
authorize #user
if #user.update(user_params)
flash[:success] = "You have successfully updated your profile!"
redirect_to user_path(#user)
else
render :edit
end
end
def crop
#user = User.find(params[:id])
authorize #user
end
def index
end
private
def user_params
params.require(:user).permit(:poster_image_crop_x, :poster_image_crop_y, :poster_image_crop_w, :poster_image_crop_h)
end
end
Routes
Rails.application.routes.draw do
resources :users,only: [:show] do
member do
get :crop
end
end
devise_for :users, :controllers => { :omniauth_callbacks => "callbacks",:registrations => :registrations,:passwords => "passwords" }
as :user do
get "/login" => "devise/sessions#new"
get "/register" => "devise/registrations#new"
get "/edit" => "devise/registrations#edit"
delete "/logout" => "devise/sessions#destroy"
end
The code by Devise is suggesting to create your own controller. They probably always require password to be passed if it comes from an action in the UsersController. So you should create a seperate controller, let's call it ProfilesController, this controller is like your normal controller although it does not update a Profile model, but the User model directly... nothing special actually, just check authorization and let the User update any field you'd like directly on the User mode, do not forget to authorize the fields you'd wish to let the user update:
class ProfilesController < ApplicationController
def index
end
....... more code
def update
#user = User.find(params[:id])
authorize #user
if #user.update(user_params)
flash[:success] = "You have successfully updated your profile!"
redirect_to user_path(#user)
else
render :edit
end
end
....... more code
private
def user_params
params.require(:user).permit(:poster_image_crop_x, :poster_image_crop_y, :poster_image_crop_w, :poster_image_crop_h)
end
end
And add resources :profiles to your routes file.
error
uninitialized constant YourSpace::UsersController::User
controller
class YourSpace::UsersController < ApplicationController
def new
#title = YourSpace
end
def edit
#title = YourSpace
#user = User.find(params[:id])
end
def update
name = params[:user][:name]
if name.blank?
flash[:notice] = "Name can not be blank dawg!"
redirect_to :back
else
User.find(params[:id]).update_attributes(params[:user])
# redirect_to :action 'show'
redirect_to :action => :show
# render :action => 'show'
end
end
def index
#title = YourSpace
#users = User.limit(100).order('created_at DESC')
end
def show
#title = YourSpace
#user = User.find(params[:id])
end
end
routes
Rails.application.routes.draw do
root 'site#home'
get '/about', to: 'site#about', as: :about
namespace :your_space do
resources :users
end
namespace :word_cloud do
resources :words, :only => [:index, :create]
end
namespace :word_clock do
resources :page, :only => [:index]
end
namespace :wish do
resources :page, :only => [:index]
end
end
when firing up the rails server, I get error in the YourSpace UsersController where this line of code #users = User.limit(100).order('created_at DESC') is apparently all jacked up. Please know I'm trying to duplicate 180 websites in 365 days which is mostly built using ruby and rails. I'm following closely along the repo to build muscle memory. very much new to learning how to think, and programming.
First thought was wrong.. to solve the problem change User to ::User
My first thought is that you need to put this YourSpace::UsersController in app/controllers/your_space/users_controller.rb. Rails forces directory structure.
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
So I am trying to make a link to user's profile! So I have this in User's controller:
class UsersController < ApplicationController
def new
#defining the "#user" object for the form_for
#user = User.new
end
#defining a function for the "show" html file
def show
#get user id by URL address
#user = User.find(params[:id])
end
#handling user login succes or failure
def create
#user = User.new(params[:user])
if #user.save
#using "flash" variable Ruby
#flash[:success] = "Welcome to the Sample App!" <<< use this !!
#render success page
redirect_to #user
else
#render failure page (using error partial page)
render 'new'
end
end
#mine to show user profile
def show_user
render 'show'
end
end
and in my routes.rb I got:
DemoApp::Application.routes.draw do
get "intergration_test/authentication_pages"
#Removed!
#get "users/new"
#ROOT page
root to: 'static_pages#home'
#My routes
match '/user_profile', to: 'users#show_user'
#REST architecture for users
resources :users
#including the Sessions action
resources :sessions, only: [:new, :create, :destroy]
match '/signup', to: 'users#new'
match '/signin', to: 'sessions#new'
#Note the use of via: :delete for the signout route, which indicated that it should be invoked using an HTTP DELETE request
match '/signout', to: 'sessions#destroy', via: :delete
end
So why does
#mine to show user profile
def show_user
render 'show'
end
returns me the error:
undefined method `email' for nil:NilClass
it is like the user is null! I am already logged in! so I should have a user active.
even if I use redirect_to #user it does not work! help?
I'm assuming the show template has access to 'user' via the #user instance variable. If so, then you need to set the instance variable:
def show_user
#user = current_user // Or other method for getting the logged in user.
render 'show'
end
let's say that you are in index page , and you want to create a link to redirect to a user you can just use something like :
<%= link_to 'Show User', current_user %>
the user is the user object and from the default rest route it will take you to show action of the page, so no need to create an action in your controller 'show_user'
And can your provide the view of the controller and how you call the show_user action
routes.rb
PASFramework::Application.routes.draw do |map|
resources :users do
collection do
get :index
get :edit
post :update
get :show
end
end
root :to => 'users#index'
end
==================================================================
navigation.rb
# Configures your navigation
SimpleNavigation::Configuration.run do |navigation|
navigation.items do |primary|
primary.item :users, 'Welcome User', root_path do |users|
users.item :edit, 'Edit Profile', edit_users_path
end
end
end
==================================================================
User_controller
class UsersController < ApplicationController
def index
user = current_facebook_user.fetch
#u = User.find_by_facebook_id(user.id)
if #u.nil?
#u = User.find_or_create_by_facebook_id(user.id)
#u.update_attributes( :first_name => current_facebook_user.first_name,
:last_name => current_facebook_user.last_name )
gflash :notice => "Welcome, #{current_facebook_user.name} "
else
gflash :notice => "Welcome back, #{current_facebook_user.first_name} #{current_facebook_user.last_name}"
end
return
rescue Exception
logger.info "Problem"
logger.error($!)
top_redirect_to auth_url
end
def show
end
def edit
user = current_facebook_user.fetch
#user = User.find_all_by_facebook_id(user.id)
end
def update
user = current_facebook_user.fetch
#user = User.find_all_by_facebook_id(user.id)
if #user.update_attributes(:first_name => params[:first_name],
:last_name => params[:last_name])
redirect_to user_path, :notice => t('users.update_success')
else
render :action => 'edit'
end
end
end
==========================================================================
The menu is created really well and thanks for this awesome plugin. But when I click edit user I get an error:
ActionView::Template::Error (No route matches {:action=>"show", :controller=>"users"}):
Can someone help me with that please? Can someone explain me why in routes.rb resources user only is not working instead of the collection thing?
Thanks in advance.
It's because of how you are defining the show route.
resources :users do
collection do
get :index
get :edit
post :update
get :show #this is your problem
end
end
Trying renaming this to a different action. The default show route is getting overridden.
resources :users do
collection do
get :index
get :edit
post :update
get :second_show # of course rename this to a better name
end
end