unknown attribute 'email' for [has_many association] when trying to create - ruby-on-rails

I have a model User that i've set up a has_many/belongs_to association with posts, and I'm trying to test my posts controller in rspec. However, when I try to create a post that belongs to a user, I get the error: undefined method 'email=' for #<Post:0x00000...>
I am creating the Post like so:
before(:each) do
#user = User.create!({email: "email#gmail.com", password: "password"})
#post = #user.posts.create!({title: "title", content: "content"})
end
I'm not sure why it's trying to find an email method for the post, as there is none that exists.
I also get this error when I try to create a new post in the rails console. I can do p = Post.new(...), but i get the error when I save it. (p.save!)
I also get the error when I try to create a post like so:
Post.create({title: "title", content: "content", user_id: 1 })
Does anyone have any idea why this error is showing up and how I can fix it? Thanks!
--
My post model looks like this:
class Post < ActiveRecord::Base
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
belongs_to :user
end

This line in the Post model is causing the problems. devise by default requires an email column so that is why it's complaining of it not existing. Simply remove the line from the Post model.
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable

Based on the given information, this is how the files should look:
models/user.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
has_many :posts
end
models/post.rb
class Post < ActiveRecord::Base
belongs_to :user
end
User migration
class DeviseCreateUsers < ActiveRecord::Migration[5.0]
def change
create_table :users do |t|
## Database authenticatable
t.string :name, null: false
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, default: 0, null: false
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.inet :current_sign_in_ip
t.inet :last_sign_in_ip
## Confirmable
t.string :confirmation_token
t.datetime :confirmed_at
t.datetime :confirmation_sent_at
t.string :unconfirmed_email
t.timestamps null: false
end
add_index :users, :name
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
add_index :users, :confirmation_token, unique: true
add_index :users, :unlock_token, unique: true
end
end
Post migration
class CreatePosts < ActiveRecord::Migration[5.0]
def change
create_table :notes do |t|
t.string :title, null: false
t.text :content, null: false
t.timestamps null: false
end
end
end

Related

Devise sign-up request method post using Postman

I created an only API rails project and added devise user model
now I am trying to sign-up using Postman but it does not save the new user on the
database
however, it does not return an error as well.
Postman post request and parameters passed
My app controller with the additional permitted attributes
`class ApplicationController < ActionController::API
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
attributes = :name, { roles: [] }
devise_parameter_sanitizer.permit(:sign_up, keys: attributes)
devise_parameter_sanitizer.permit(:account_update, keys: attributes)
end
end`
Devise User model with validations
`class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
validates :name, presence: true
validates :password, presence: true
validates :email, presence: true
validates :roles, presence: true
has_many :reservations, dependent: :destroy
has_many :vechiles, through: :group_entities
end`
The migration file for the devise user table
class DeviseCreateUsers < ActiveRecord::Migration[7.0]
def change
create_table :users do |t|
t.string :name, null: false
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
# t.integer :sign_in_count, default: 0, null: false
# t.datetime :current_sign_in_at
# t.datetime :last_sign_in_at
# t.string :current_sign_in_ip
# t.string :last_sign_in_ip
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
t.timestamps null: false
end
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
# add_index :users, :confirmation_token, unique: true
# add_index :users, :unlock_token, unique: true
end
end
Roles col. added to user table
class AddRolesToUsers < ActiveRecord::Migration[7.0]
def change
add_column :users, :roles, :text, array: true, default: []
end
end
My Routes.rb
# frozen_string_literal: true
Rails.application.routes.draw do
devise_for :users
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
resources :users, only: [:index]
# Defines the root path route ("/")
# root "articles#index"
end

Rails devise isn't saving the password upon registration

I am using devise 4.8.1 with rails 7.0.3 and postgresql, I just started using devise, and I generated the views using rails g devise:views and then applied the migration using "rails db:migrate"
This is my user model:
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable, :confirmable
has_many :posts, foreign_key: 'author_id'
has_many :comments, foreign_key: 'author_id'
has_many :likes, foreign_key: 'author_id'
attr_accessor :password, :password_confirmation
validates :name, presence: true
validates :PostsCounter, presence: true, numericality: { greater_than_or_equal_to: 0 }
def recent_posts
posts.order(created_at: :desc).limit(3)
end
end
This is the migration that I added:
# frozen_string_literal: true
class AddDeviseToUsers < ActiveRecord::Migration[7.0]
def self.up
change_table :users do |t|
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
# t.integer :sign_in_count, default: 0, null: false
# t.datetime :current_sign_in_at
# t.datetime :last_sign_in_at
# t.string :current_sign_in_ip
# t.string :last_sign_in_ip
## Confirmable
t.string :confirmation_token
t.datetime :confirmed_at
t.datetime :confirmation_sent_at
t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
# Uncomment below if timestamps were not included in your original model.
# t.timestamps null: false
end
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
add_index :users, :confirmation_token, unique: true
# add_index :users, :unlock_token, unique: true
end
def self.down
# By default, we don't want to make any assumption about how to roll back a migration when your
# model already existed. Please edit below which fields you would like to remove in this migration.
raise ActiveRecord::IrreversibleMigration
end
end
This morning devise was working fine, when I sign up the password gets encrypted and then saved now when I sign up and then try to login it says invalid email/password, when I checked my PostgreSQL database I found out that nothing is getting saved in the encrypted_password column as shown in this picture, I tried searching online but couldn't find any solution, I also tried to reinstall the gems and nothing worked, I am not sure how to fix this issue, please assist me with this.
If you need any more information about my code please let me know.
Edit: I am not sure if it's okay to share this but this is my GitHub repository and branch that has the issue (the issue is only presented in that branch feature/devise), I tried to share some pieces of the code I have but it's better to see the project structure in my opinion.
Did you try creating user from the rails console? If it gets saved with encrypted password, there is nothing wrong in the code. If it does not, it will throw the error and you can debug from there?

Devise not working in production due to nil to_sym method

I have been trying to add user login / authentication to my RoR site. I am using Devise.
Things work fine in my dev instance (I use Cloud9, in case useful).
However when I push to Heroku / production, for any page related to the user functionality (e.g. User Sign up, User login, or a page which checks if the user is logged in), it errors out. All Heroku gives me is:
NoMethodError (undefined method `to_sym' for nil:NilClass):
Just looking for some ideas on what could be happening?
user.rb:
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
enum role: [:user, :business, :admin]
after_initialize :set_default_role, :if => :new_record?
def set_default_role
self.role ||= :user
end
DeviseCreateUsers migration:
# frozen_string_literal: true
class DeviseCreateUsers < ActiveRecord::Migration[5.0]
def change
create_table :users do |t|
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
# t.integer :sign_in_count, default: 0, null: false
# t.datetime :current_sign_in_at
# t.datetime :last_sign_in_at
# t.string :current_sign_in_ip
# t.string :last_sign_in_ip
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
t.integer :role, default: 0
t.timestamps null: false
end
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
# add_index :users, :confirmation_token, unique: true
# add_index :users, :unlock_token, unique: true
end
end
Many thanks!

querying images/text from tables onto view

I am trying to create a view for photo uploads for users. I'm new to rails so I'm not quite sure if I am doing this correctly because I'm not quite sure how all the pieces fit. I am using devise and also carrierwave for user authentication and image storage in database. I'm not quite sure what to do with the params for IncomePicture_params. I want to create a view that will allow me to call and display the images and the texts for pictures of the user
I am using rails 4
Models:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:rememberable, :validatable
validates_presence_of :username
has_many :expense_pictures
has_many :income_pictures
end
class IncomePicture < ActiveRecord::Base
belongs_to :user
mount_uploader :image, ImageUploader
has_one :income_text
accepts_nested_attributes_for :income_text
end
class IncomeText < ActiveRecord::Base
belongs_to :income_picture
end
controller:
class UserController < ApplicationController
def create
User.create(user_params)
end
private
def user_params
# required input for params
# permit - returns a version of the params hash with ony the permitted attributes
params.require(:user).permit(:name, :email, :password, :password_confirmation, )
end
end
class IncomePicturesController < ApplicationController
def new
#income_picture = IncomePicture.new(IncomePicture_params)
end
def create
end
def destroy
end
private
def IncomePicture_params
params.require(:income_picture).permit(:image, income_text_attributes: [:amount])
end
end
schema
ActiveRecord::Schema.define(version: 20140723044409) do
create_table "income_pictures", force: true do |t|
t.datetime "created_at"
t.datetime "updated_at"
t.string "image"
t.integer "user_id"
end
add_index "income_pictures", ["user_id"], name: "index_income_pictures_on_user_id"
create_table "income_texts", force: true do |t|
t.datetime "created_at"
t.datetime "updated_at"
t.integer "income_picture_id"
t.string "amount"
end
add_index "income_texts", ["income_picture_id"], name: "index_income_texts_on_income_picture_id"
create_table "users", force: true do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.datetime "remember_created_at"
t.datetime "created_at"
t.datetime "updated_at"
t.string "username"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
end

NoMethodError in Devise::SessionsController#create undefined method `current_sign_in_at'

I am getting the following error when I try to sign in in my rails app. I used devise for authentication. My error is
NoMethodError in Devise::SessionsController#create
undefined method `current_sign_in_at'
My user model is
models/user.rb
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable
attr_accessible :admin,:first_name, :last_name, :profile_name, :college_name, :email, :password, :password_confirmation, :remember_me, :provider, :uid
def admin?
end
def self.find_for_facebook_oauth(auth)
where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user|
user.provider = auth.provider
user.uid = auth.uid
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
#user.name = auth.info.name # assuming the user model has a name
#user.image = auth.info.image # assuming the user model has an image
user.save!
end
end
end
My schema is
db/schema.rb
ActiveRecord::Schema.define(:version => 20140126101946) do
create_table "levels", :force => true do |t|
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "users", :force => true do |t|
t.string "first_name"
t.string "last_name"
t.string "profile_name"
t.string "college_name"
t.string "email", :default => "", :null => false
t.string "encrypted_password", :default => "", :null => false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "provider"
t.string "uid"
t.boolean "admin", :default => false
end
add_index "users", ["email"], :name => "index_users_on_email", :unique => true
add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true
end
The code in my devise_create_users.rb is
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
t.string :first_name
t.string :last_name
t.string :profile_name
t.string :college_name
## Database authenticatable
t.string :email, :null => false, :default => ""
t.string :encrypted_password, :null => false, :default => ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, :default => 0
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
My trackable was commented and I removed the comments and then ran rake db:migrate but nothing happened. Now I cannot remove trackable as I need it. What I need is that somehow I can keep my devise as it is and also add trackable to it in such a way that it gets added to the schema.rb as well.
To add new columns to existing tables, simply updating already run migration is not going to work as the schema is at a later version than your existing migration's version. If you wish to modify the existing migration, you could run a down migration with:
rake db:migrate:down VERSION=20140126101944 # use version of the user migration
Then modify the migration adding the new columns as you've already done, then run up migration using:
rake db:migrate:up VERSION=20140126101944 # use version of the user migration
A better approach is to add a new migration with the change if your application is already in production.
To add the trackable columns to existing users table:
class AddTrackableColumnsToUser < ActiveRecord::Migration
def change
change_table :users do |t|
## Trackable
t.add_column :sign_in_count, :integer, :default => 0
t.add_column :current_sign_in_at, :datetime
t.add_column :last_sign_in_at, :datetime
t.add_column :current_sign_in_ip, :string
t.add_column :last_sign_in_ip, :string
end
end
end
Then run db:migrate:
rake db:migrate
In your models/user.rb
Change
devise :database_authenticatable, :registerable, :recoverable, :rememberable,
:trackable, :validatable, :omniauthable
to
devise :database_authenticatable, :registerable, :recoverable, :rememberable,
:validatable, :omniauthable
i.e. remove :trackable

Resources