Route redirecting issue with devise and rails - ruby-on-rails

I have a has_one association in my model with my user. What I'm trying to do here is simple but I'm having a hard time understanding whats wrong here. So since I have a has_one association with my model, in my mind I was simply thinking that if the user has already created the model associated with the has_one association if he tries accessing "localhost3000/model/new" I would redirect him to the edit page of this particular model. Here is what I have but its telling me its not working as intended. It's as if my if statement is not catching anything
class BusinessesController < ApplicationController
before_action :set_business, only: [:show, :edit, :update, :destroy]
def index
#businesses = Business.all
#buzzs = Buzz.all
end
def show
end
def new
if current_user.business.nil?
#business = current_user.build_business
else
render 'edit'
end
end
def edit
end
def create
#business = current_user.build_business(business_params)
if #business.save
redirect_to #business, notice: 'Business was successfully created.'
else
render "new"
end
end
This error does not make a lot of sense to me because it says its an error in the "new" controller which would have rendered it to the edit path thus not being nil

This is happening because you're not setting #business when redirecting to 'edit'. Try this:
def new
if current_user.business.nil?
#business = current_user.build_business
else
#business = current_user.business
render 'edit'
end
end

Related

Tree comments Ruby on Rails

Trying to implement a tree-like comments on the site via a gem - acts-as-commentable-with-threading.
Comments are excellent and are displayed on the site when I visit a site under the user (implemented via the gem devise).
But when trying to view pages anonymously, naturally, I receive an error that id is not may be due to the elements onto a blank.
This is my controller recipes_controller.rb:
class RecipesController < ApplicationController
before_action :authenticate_chef!, except: [:index, :show]
def show
#recipe = Recipe.find(params[:id])
#comments = #recipe.comment_threads.order('created_at desc')
#user_who_commented = current_chef
#new_comment = Comment.build_from(#recipe, #user_who_commented.id, "")
end
...
comments_controller.rb:
class CommentsController < ApplicationController
before_action :authenticate_chef!
def create
commentable = commentable_type.constantize.find(commentable_id)
#user_who_commented = current_chef
#comment = Comment.build_from(commentable, #user_who_commented.id, body)
respond_to do |format|
if #comment.save
make_child_comment
format.html { redirect_to(:back, :notice => 'Comment was successfully added.') }
else
format.html { render :action => "new" }
end
end
end
...
recipe.rb:
class Recipe < ActiveRecord::Base
acts_as_commentable
...
In views (recipes/show.html.erb) I put this render :
<%= render partial: "comments/template", locals: {commentable: #recipe, new_comment: #comment} %>
I think that you may need in the controller to create something like a design if ... else for those who just browse the site, because the default at this point in the show method is set current_chef, because of what and error.
You need to handle the special case in view(probably comment template) for anonymous visit. Cause then current_chef would be nil. So where you're using it in view and controller, handle that properly.
A tip: You don't need to assign current_chef to any instance variable actually. It's already a helper method. You can call it directly from view.

Rails 4: One-to-one controller issue

I'm building an app which consists on sharing résumés. I am using Devise gem. Each user is able to create only one résumé. I made the models and and their relations. Resume belongs_to User and User has_one 'Resume'.
After making the views, I wanted to test my app but I got the error: undefined methodbuild' for nil:NilClass`
Here is my ResumeController and my routes.rb
class ResumeController < ApplicationController
before_action :find_resume, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:show]
def show
# #resume = Resume.find_by(params[:id])
end
def new
#resume = current_user.resume.build
end
def create
#resume = current_user.resume.build(resume_params)
if #resume.save
redirect_to #resume, notice: "resume was successfully created"
else
render 'new'
end
end
def edit
end
def update
if #resume.update(pin_params)
redirect_to #resume, notice: "resume was successfully updated"
else
render 'edit'
end
end
def destroy
#resume.destroy
redirect_to root_path
end
private
def resume_params
params.require(:resume).permit(:title, :description)
end
def find_resume
#resume = resume.find(params[:id])
end
end
Routes.rb
Rails.application.routes.draw do
devise_for :users
resources :resume, except: [:index]
get 'static_pages/index'
root to: "static_pages#index"
end
I just want the user to be able to create only one Resume and then he will be able to share it.
Update: After following messanjah's answer there was another error coming from the _form.html.erb: undefined method resumes_path' for #<#<Class:0x00...>. Here is the gist with forms and model: goo.gl/XvW2LH So you can see all the files closely.
Without more knowledge of where the error is happening, I can only suggest some areas that might be suspect.
To build a has_one relationship, you must use the build_*association* constructor.
def new
#resume = current_user.build_resume
end
def create
#resume = current_user.build_resume(resume_params)
end

Keep Receiving an "Unknown attribute=user_id" error

First time poster, long time lurker here. I have a Users model and controller for a little video game application for Rails that I'm currently making. So I've read a couple of answers on here regarding this issue, but none of the answers really seem to have helped me. People have suggested adding a "user_id" column to my Users table, but my point of contention is, I thought the "user_id" was automatically made in Rails? Even if I use a user.inspect, I still see a user_id=7show up on the page. However, I still get the unknown attribute error when attempting to create a game and assign to the current user. Any help would be most appreciated in pinpointing the cause and solution to this. Thanks!
app/controllers/users_controller.rb:
class UsersController < ApplicationController
skip_before_filter :require_authentication, only: [:new, :create]
def index
#users = User.all
end
def show
end
def new
#user = User.new
end
def edit
#user = current_user
end
def create
#user = User.create!(user_params)
session[:user_id] = #user.id
redirect_to users_path, notice: "Hi #{#user.username}! Welcome to DuckGoose!"
end
def update
current_user.update_attributes!(user_params)
redirect_to users_path, notice: "Successfully updated profile."
end
def destroy
#user = User.find(params[:id])
#user.destroy
redirect_to users_url, notice: 'User was successfully destroyed.'
end
private
def user_params
params.require(:user).permit(:username, :firstname, :lastname, :email, :password, :password_confirmation)
end
end
app/config/routes.rb:
NkuProject::Application.routes.draw do
resources :users do
resources :games
end
resources :sessions
resources :games
get "sign_out", to: "sessions#destroy"
get "profile", to: "users#edit"
root to: "sessions#new"
end
app/controllers/games_controller.rb
class GamesController < ApplicationController
def new
#game = Game.new
end
def index
#games = Game.all
end
def destroy
#game = Game.find(params[:id])
#game.destroy
redirect_to games_url, notice: 'Game was successfully deleted.'
end
def create
#game = current_user.games.build(game_params)
if #game.save
redirect_to #game, notice: "Game successfully added"
else
render :new
end
end
def show
#game = Game.find(params[:id])
end
private
def game_params
params.require(:game).permit!
end
end
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_filter :require_authentication
def current_user
#current_user ||= User.find_by(id: session[:user_id]) if session[:user_id].present?
end
helper_method :current_user
def require_authentication
if current_user
true
else
redirect_to new_session_path
end
end
end
I'm sure I'm missing some code to put in for reference, but if I need anything else please let me know.
Looking at the way your controller actions are defined, I can safely say that User and Game have a 1-M relationship, i.e.,
class User < ActiveRecord::Base
has_many :games
end
class Game < ActiveRecord::Base
belongs_to :user
end
Now, based on that games table must have a field named user_id. Rails is not going to create it for you unless you specify it. You need to add field user_id in games table by creating a migration for the same. Right now, it doesn't seem like you have user_id foreign_key field in games table. Hence, the error while saving games record.

How to restrict foreign keys in Rails' update controller action?

In my Rails app I have invoices which in turn can have many projects.
model:
class Invoice < ActiveRecord::Base
attr_accessible :project_id
end
controller:
class InvoicesController < ApplicationController
before_filter :authorized_user, :only => [ :show, :edit, :destroy ]
before_filter :authorized_project, :only => [ :create, :update ]
def create # safe
#invoice = #project.invoices.build(params[:invoice])
if #invoice.save
flash[:success] = "Invoice saved."
redirect_to edit_invoice_path(#invoice)
else
render :new
end
end
def update # not safe yet
if #invoice.update_attributes(params[:invoice])
flash[:success] = "Invoice updated."
redirect_to edit_invoice_path(#invoice)
else
render :edit
end
end
private
def authorized_user
#invoice = Invoice.find(params[:id])
redirect_to root_path unless current_user?(#invoice.user)
end
def authorized_project
#project = Project.find(params[:invoice][:project_id])
redirect_to root_path unless current_user?(#project.user)
end
end
My biggest concern is that a malicious user might, one day, create an invoice that belongs to the project of another user.
Now thanks to the help of some people on this board I managed to come up with a before_filter that makes sure that this won't happen when a project is created.
The problem is I don't understand how to apply this filter to the update action as well.
Since the update action does not make use of Rails' build function, I simply don't know how to get my #project in there.
Can anybody help?
In your case I would start from current_user, not #project (provided User has_many :invoices):
current_user.invoices.build(params[:invoice])
Also instead of explicitly check current_user?(#invoice.user) you can do:
def find_invoice
#invoice = current_user.invoices.find(params[:id])
end
def find_project
#project = current_user.projects.find(params[:invoice][:project_id])
end
Wrong invoice or project will throw 500 which you may or may not want to handle.
If User has_many :invoices, :through => :projects and Project hence has_many :invoices then:
def find_invoice
#invoice = #project.invoices.find(params[:id])
end
The #project.invoices.build method creates a new Invoice that is automatically associated with that particular #project. You don't have to do any work, and there's no risk of it being linked to the wrong project.
You'll want to be sure that project_id is not an accessible attribute, though.

restricting users to create new article in blog gives " undefined method `is_admin?' for nil:NilClass" in ruby on rails app

I am implementing blog app in ruby on rails where I want to restrict normal user( only admin can create) from creating new articles. For this purpose, I have put befor_filter in articles_controller.rb file which is following. I have hided create button from user in UI but still normal user can create new article by typing in address bar of browser.By using below code, normal user can not go on new article page but it gives me "undefined method `is_admin? when i type in address bar. For more info, I have implemented devise for user authentication.
class ArticlesController < ApplicationController
before_filter :is_user_admin, only: [:new, :create]
def is_user_admin
unless current_user.is_admin?
:root
return false
end
end
end
class ArticlesController < ApplicationController
before_filter :is_user_admin, only: [:new, :create]
def is_user_admin
unless current_user.is_admin?
:root
return false
end
end
def index
#articles = Article.all(:order => "created_at DESC")
end
def show
#article = Article.find(params[:id])
end
def new
#article = Article.new
end
def create
#article = Article.new(params[:article])
#article.user_id = current_user.id
#article.save
redirect_to article_path(#article)
end
def destroy
#article = Article.find(params[:id])
#article.destroy
redirect_to action: 'index'
end
def edit
#article = Article.find(params[:id])
end
def update
#article = Article.find(params[:id])
#article.update_attributes(params[:article])
flash.notice = "Article '#{#article.title}' Updated!"
redirect_to article_path(#article)
end
end
applicaiton_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
def after_sign_in_path_for(user)
if current_user.is_admin?
dashboard_index_path
else
:root
end
end
end
Basically, I want to restrict normal user (other than admin) to create , update or delete articles either from UI(this is done) or typing address in address bar.
I have no idea why i am getting this and what can i do to avoid this. Should i write above method in application_controller.rb file.
You propably want to redirect users to login so they can't access the action in your controller, if they're not admins. Hence, you could do something like this:
def is_user_admin
redirect_to(action: :index) unless current_user.try(:is_admin?)
end
Your current_user is nil apparently.
You should put before_filter :authenticate_user!, :except => [:show, :index] at the top of your controller in order to authenticate user.
Make sure that at least there is an user before checking for the permission. You can do that adding this code to every controller that requires an authentication:
before_filter :authenticate_user!
Doing this, you will always have a current user and hence will be able to check for its permission the way you pointed on your question.

Resources