Rails/Heroku: undefined method `events' for nil:NilClass - ruby-on-rails-3

I have a method that works locally on my machine but it fails in Heroku. Heroku logs say:
NoMethodError (undefined method `events' for nil:NilClass)
I have used heroku console for an equivalent of this method and it works so there is data that supports it. The method is:
def index
#events = current_user.school.events
end
I am using Devise which I believe gives me the current_user method. The equivalent, a = User.first.school.events yields the true instance value with data. The User.first yields correct data.
Here are my models:
class School < ActiveRecord::Base
#validates_presence_of :name
has_many :events, :dependent => :destroy
has_many :users, :dependent => :destroy
belongs_to :user
belongs_to :event
def self.fetch_for_name(_name)
school = self.new(:name => _name)
end
end
class User < ActiveRecord::Base
belongs_to :school
rolify
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :name, :email, :password, :password_confirmation, :remember_me
end
class Event < ActiveRecord::Base
belongs_to :school
end
It would be like me if I overlooked some simple, basic thing but if I can do this correctly in Heroku console, why would this method break. Another unrelated page works correctly on Heroku.

current_user is the user that is logged in. It doesn't necessarily mean User.first. This should be the same locally as on Heroku. If you're having trouble figuring out what user is logged in you can add this to your application controller
before_filter :debug
def debug
Rails.logger.info("Current User is: #{current_user.inspect}")
end
And then view the output with $ heroku logs --tail It should show you the current value of the current_user. At the end of the day what #thesis said is correct, you have a user that does not have a school associated with it.

Related

Rails Polymorphing has_one association redirect_to controller

In my app, user is used for the authentication phase, and with a polymorphic has_one association, it will be associated at different type of users, with different actions.
This is the user model:
class User < ApplicationRecord
has_secure_password
validates :username, presence: true,
uniqueness: true
belongs_to :role, :polymorphic => true, dependent: :destroy
end
and this is one of the models associated
class Guest < ApplicationRecord
has_one :user, as: :role
end
Logging and authentication call home_index_path, and the current user is stored in current_user.
In the Home Controller i have:
def index
if current_user
redirect_to current_user.role
else
render 'unlogged'
end
end
In route.rb i have:
resource :guest do
member do
get 'dashboard'
end
end
resolve ('Guest') {[:guest]}
Now the problem: assuming that the user is a guest, in this way i'm redirected to method show of GuestsController, but i need that is redirected to method dashboard.
How can i do?
Ok, i've resolved with polymorphing_path
redirect_to polymorphic_path([:dashboard, current_user.role])

Devise's current_user only works for admins

I've got a standard User model, it has in it an admin boolean. All's well and good for users that have that set to true, but for normal users I get this error:
undefined local variable or method `current_user'
app/models/doc.rb:18:in `mine'
app/controllers/docs_controller.rb:9:in `index'
The Doc model on line 18 reads like this:
def self.mine
where(:user_id => current_user.name, :retired => "active").order('created_at DESC')
end
My User model looks like this:
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
attr_accessor :current_password
attr_accessible :name, :password, :password_confirmation, :current_password, :email, :remember_me, :admin
end
class Ability
include CanCan::Ability
def initialize(user)
can :manage, :all if user.admin
end
end
And in my application controller I have the following:
class ApplicationController < ActionController::Base
protect_from_forgery
after_filter :user_activity
rescue_from CanCan::AccessDenied do |exception|
redirect_to root_path
end
def admin?
self.admin == true
end
def authenticate_admin
redirect_to :new_user_session_path unless current_user && current_user.admin?
end
private
def user_activity
current_user.try :touch
end
end
I think that's everything relevant. I can't for the life of me figure this out.
the current_user helper is a controller method that is not accessible from a model. You should pass current user in as a parameter from the controller to the model.
def self.mine(current_user)
where(:user_id => current_user.name, :retired => "active").order('created_at DESC')
end
EDIT: Side note
It looks like user_id is a string in your logic. If this is what you are doing, you should reconsider. Setting up a belongs_to and a has_many with rails using identifiers in the database is far more maintainable. Using string ids is unconventional, and its a rabbit hole that ends in very bad places.

Find on has_many :through

I have 3 models: Users, Customers, Issues. Below is the code for these models
Customer model:
class Customer < ActiveRecord::Base
belongs_to :se
belongs_to :user
has_many :issues
end
Issues model:
class Issue < ActiveRecord::Base
belongs_to :customer
end
Users model:
class User < ActiveRecord::Base
has_many :ses
has_many :customers
has_many :issues, :through => :customers
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :remember_me, :first_name, :last_name, :cell_ph, :area
end
I would like to display only the issues that belong to a particular user. I am having problems making this work. Can someone suggest how I might create an index method that would accomplish this?
Here is my index method where I'm trying to use devise's current_user method to identify the user who's logged in to the view:
def index
#issues = Issue.where(:user == :current_user)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #issues }
end
end
You can't do what you're doing because an Issue doesn't have a user.
According to Rails guides (second example on http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association session), you can nest the has_many using a has_many :through.
So you should be able to do this:
current_user.issues
In addition to Rodrigo's answer, you have some bad syntax on this line:
#issues = Issue.where(:user == :current_user)
That's never going to return any results because :user == :current_user is performing a comparison of two distinct Ruby Symbol objects. That always returns false, so your statement essentially equates to Issue.where(false).
This is closer to what you need:
#issues = Issue.where(:user => current_user)
This still doesn't fix the problem you have (Issue does not have many Users), but at least the meaning is correct.

Problem with the factory girl cucumber step definitions

I am using the cucumber step definitons provided by factory girl and I can not get something to work here.
First of all, here are the involved factories:
Factory.define :user do |u|
u.name {|n| "User#{n}" }
u.first_name {|n| "FirstName#{n}"}
u.last_name {|n| "LastName#{n}"}
u.password 'please'
u.password_confirmation 'please'
end
Factory.define :lecture do |l|
l.name {|n| "Lecture#{n}"}
l.abbreviation {|n| "lec#{n}"}
l.association :admin, factory: :user
end
Here is the step I am trying to execute:
And the following Lecture exists:
| Name | Abbreviation |
| Informatik A - Algorithmen und Datenstrukturen | ainf |
I am getting this error message and have absolutely NO idea where it comes from:
User(#42819220) expected, got User(#43753000) (ActiveRecord::AssociationTypeMismatch)
features/lectures/ui.feature:11:in `And the following Lecture exists:'
And here are my model definitions:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :rememberable, :trackable
# Setup accessible (or protected) attributes for your model
attr_accessible :name, :password, :password_confirmation, :remember_me, :first_name, :last_name
validates_uniqueness_of :name
has_many :administrated_lectures, class_name: "Lecture", foreign_key: "admin_id", dependent: :nullify
end
class Lecture < ActiveRecord::Base
validates_uniqueness_of :name
validates_uniqueness_of :abbreviation
scope :ordered, order("name")
belongs_to :admin, class_name: "User"
end
I am using this with spork btw.
Kind regards,
Nils
This is most likely because of Spork.
The error is because at some point the User constant is being reloaded, but FactoryGirl is still referencing the old constant. This is because you can unload constants like this:
Object.remove_const :User
See the line in this class:
https://github.com/thoughtbot/factory_girl/blob/master/lib/factory_girl/factory.rb#L27
You can see where this error occurs by breakpointing or just inspecting somewhere around these 2 places:
https://github.com/carlhuda/bundler/blob/1-0-stable/lib/bundler/runtime.rb#L68
https://github.com/rails/rails/blob/master/activesupport/lib/active_support/dependencies.rb#L519 (this class is the main place where you'll debug the problem)
My guess is that something is reloading ActiveRecord classes, but not reloading FactoryGirl. One way around this might be to reset the FactoryGirl definitions:
Spork.each_run do
# this isn't the correct api, something like this though.
FactoryGirl.definition_file_paths = [File.join(Rails.root, 'spec', 'factories')]
FactoryGirl.find_definitions
end
Hope that helps, Lance.
Oh, damn. Got it. I set cache_classes to false somewhere in the past because proper class reloading did not work for some reason. Just made it true again, and now it works. :/

RoR3 Devise - Projects per Users

I am working on very simple application for managing user projects. There are two models, User and Project. User should view only projects they created. So, model Project has user_id column for linking with User. Models:
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable, :rememberable, :validatable
has_many :projects, :dependent => :destroy
attr_accessible :email, :password, :password_confirmation, :remember_me
end
class Project < ActiveRecord::Base
belongs_to :user
end
When user creates new project, user id should be automatically added to user_id column. This is accomplished in Project controller under create action:
def create
params[:project][:user_id] = current_user.id
#project = Project.new(params[:project])
#...
This works when I add user_id to params[:project] but I have a feeling this is not a proper way to do is. Or is it?
def create
#project = current_user.projects.build(params[:project])
#...
http://guides.rubyonrails.org/association_basics.html#has_many_collection_build