Rails - Model Testing with MiniTest and Devise gem - ruby-on-rails

I'm trying to test the User Model, which I've got Devise authentication.
But I've got a failure:
Failure:
UserTest#test_should_be_valid [/home/nikki/Documents/TheHackingProject/week06/monday/the_private_club/test/models/user_test.rb:12]:
Expected false to be truthy.
This is my user_test.rb file:
require 'test_helper'
class UserTest < ActiveSupport::TestCase
def setup
#user = User.create(
first_name: 'Marge',
last_name: 'Simpson',
email: 'marge#simpson.com'
)
end
test 'should be valid' do
assert #user.valid?
end
test 'first name cant be blank' do
#user.first_name = ""
assert_not #user.valid?
end
test 'last name cant be blank' do
#user.last_name = ""
assert_not #user.valid?
end
end
And this my schema.rb file:
ActiveRecord::Schema.define(version: 2018_11_05_115404) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "users", force: :cascade do |t|
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 "first_name"
t.string "last_name"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
end
Also, I don't understand how can I test the password which is encrypted?

Related

can't get fallbacks to work in rails + mobility

I'm having some issues with configuring the mobility gem.
If a translation isn't present, I would like to get the default translation (in this case :de should fallback to :en). I built a test which should explain what I'm struggling with. I guess it's a misconfiguration, hopefully someone can point out what I'm missing here.
# frozen_string_literal: true
require "bundler/inline"
gemfile(true) do
gem "rails", "~> 5.2.0"
gem "pg", "~> 0.12"
gem "mobility", "~> 1.2.9"
gem "i18n", "< 1.9.0"
end
require "active_record"
require "minitest/autorun"
require "mobility"
Mobility.configure do
plugins do
backend :key_value
active_record
reader
writer
column_fallback true
fallbacks({ :en => :de }) # this is the line that's giving me headaches
locale_accessors [:en, :de]
end
end
I18n.available_locales = [:en, :de]
I18n.default_locale = :en
ActiveRecord::Base.establish_connection(adapter: "postgresql", host: "localhost", database: "testing", user: "postgres", password: "password")
ActiveRecord::Schema.define do
#enable_extension "plpgsql"
create_table "mobility_string_translations", force: :cascade do |t|
t.string "locale", null: false
t.string "key", null: false
t.string "value"
t.string "translatable_type"
t.bigint "translatable_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["translatable_id", "translatable_type", "key"], name: "index_mobility_string_translations_on_translatable_attribute"
t.index ["translatable_id", "translatable_type", "locale", "key"], name: "index_mobility_string_translations_on_keys", unique: true
t.index ["translatable_type", "key", "value", "locale"], name: "index_mobility_string_translations_on_query_keys"
end
create_table "mobility_text_translations", force: :cascade do |t|
t.string "locale", null: false
t.string "key", null: false
t.text "value"
t.string "translatable_type"
t.bigint "translatable_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["translatable_id", "translatable_type", "key"], name: "index_mobility_text_translations_on_translatable_attribute"
t.index ["translatable_id", "translatable_type", "locale", "key"], name: "index_mobility_text_translations_on_keys", unique: true
end
create_table "contents", id: :serial, force: :cascade do |t|
t.string "key"
t.text "body"
end
end
class Content < ActiveRecord::Base
self.table_name = "contents"
extend Mobility
translates :key, type: :string
translates :body, type: :text
end
class BugTest < ActiveSupport::TestCase
test "should have fallbacks enabled" do
model = Content.create!
model.key = "foo"
model.body = "bar"
model.save
model.reload
assert model.key # works as expected
assert model.body # works as expected
assert model.key(locale: :de) # fails. expecting "foo"
assert model.body(locale: :de) # fails. expecting "bar"
assert model.key_de # fails
assert model.body_de # fails
end
end

ActiveRecord::RecordInvalid: Validation failed: Users must exist

I am trying to seed an sqlite3 db from a json file as a project. I have two models user and logins.
require 'json'
records = JSON.parse(File.read('db/people.json'))
records.each do |record|
User.create!(record.except('logins').merge('password' => 'encrypted password'))
end
records.each do |record|
Login.create!(record['logins'])
end
When I run my rails db:seed it successfully seeds the users and then fails when creating the logins with this error ActiveRecord::RecordInvalid: Validation failed: Users must exist It may be something with my schema or my seed script im not sure which
ActiveRecord::Schema.define(version: 2020_03_30_164743) do
create_table "logins", force: :cascade do |t|
t.datetime "date"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.index ["user_id"], name: "index_logins_on_user_id"
end
create_table "users", force: :cascade do |t|
t.string "first_name"
t.string "last_name"
t.string "city"
t.string "state"
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.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
end
Here is a link to my source code https://github.com/jslack2537/apiDemoApp
it may work if you write the login inside the same loop..
records.each do |record|
u = User.new(record.except('logins').merge('password' => 'encrypted password'))
u.logins = record['logins'].map{|l| Login.new(l)}
u.save!
end

NameError in PostsController#index

I have used 4 important gems
gem 'activeadmin'
gem 'devise'
gem 'cancancan', '~> 2.0'
gem 'friendly_id', '~> 5.2.4'
I have 2 main Controller "User" and "Post" and registered in active_admin(rails generate active_admin:resource User and rails generate active_admin:resource Post).I have used cancancan for the authorization.
I have defined the ability in
ability.rb
if user.admin?
can :manage, :all
else
can :read, Posts
end
ApplicationController.rb
class ApplicationController < ActionController::Base
protect_from_forgery
rescue_from CanCan::AccessDenied do |exception|
respond_to do |format|
format.json { head :forbidden, content_type: 'text/html' }
format.html { redirect_to main_app.root_url, notice: exception.message }
format.js { head :forbidden, content_type: 'text/html' }
end
end
def current_ability
#current_ability ||= AccountAbility.new(current_admin_user)
end
end
schema.rb
ActiveRecord::Schema.define(version: 2019_02_14_200911) do
create_table "active_admin_comments", force: :cascade do |t|
t.string "namespace"
t.text "body"
t.string "resource_type"
t.integer "resource_id"
t.string "author_type"
t.integer "author_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["author_type", "author_id"], name: "index_active_admin_comments_on_author_type_and_author_id"
t.index ["namespace"], name: "index_active_admin_comments_on_namespace"
t.index ["resource_type", "resource_id"], name: "index_active_admin_comments_on_resource_type_and_resource_id"
end
create_table "admin_users", force: :cascade do |t|
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.boolean "admin", default: true
t.index ["email"], name: "index_admin_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_admin_users_on_reset_password_token", unique: true
end
create_table "categories", force: :cascade do |t|
t.string "title"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "posts", force: :cascade do |t|
t.string "title"
t.text "body"
t.datetime "published_at"
t.integer "user_id"
t.integer "category_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "slug"
t.index ["category_id"], name: "index_posts_on_category_id"
t.index ["slug"], name: "index_posts_on_slug", unique: true
t.index ["user_id"], name: "index_posts_on_user_id"
end
create_table "users", force: :cascade do |t|
t.string "name"
t.string "email"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "slug"
t.boolean "admin", default: false
t.index ["slug"], name: "index_users_on_slug", unique: true
end
end
Goal
My goal is: 1. Only Admin can post,add user, add category basically manage all.
2. guest User can only read.
So I used cancancan gem to do authorization. But I am getting error:
uninitialized constant ApplicationController::AccountAbility
Extracted source (around line #12):
end
def current_ability
#current_ability ||= AccountAbility.new(current_admin_user)
end
end
And I have uploaded on git if you need any further information.
It will be great if you can help me. Thanks in advance.
The NameError is because your model is named Ability, not AccountAbility, so change your current_ability method to:
def current_ability
#current_ability ||= Ability.new(current_admin_user)
end

undefined method `admin?' with Cancan

I have a problem finding out how to check for admin rights in CanCanCan.
With
if user.admin? I get undefined method
if user.is? I get undefined method
if user.has_attribute?(:admin)
if user.user_type == "admin" I get undefined method
I had some hopes with has_attribute, but it does not help, even if I get no alert. A puts 'hey' proves it in the console.
I started learning Rails a month ago and I experienced some limitations due to windows. Is it possible that my problem occurs because of windows?
On the other hand, if user.present? works and it gives some hopes again.
My user model:
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :posts, dependent: :destroy
end
And the DB fields
create_table "active_admin_comments", force: :cascade do |t|
t.string "namespace"
t.text "body"
t.string "resource_type"
t.integer "resource_id"
t.string "author_type"
t.integer "author_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["author_type", "author_id"], name: "index_active_admin_comments_on_author_type_and_author_id"
t.index ["namespace"], name: "index_active_admin_comments_on_namespace"
t.index ["resource_type", "resource_id"], name: "index_active_admin_comments_on_resource_type_and_resource_id"
end
create_table "admin_users", force: :cascade do |t|
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.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"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["email"], name: "index_admin_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_admin_users_on_reset_password_token", unique: true
end
create_table "posts", force: :cascade do |t|
t.string "title"
t.text "body"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "image_file_name"
t.string "image_content_type"
t.integer "image_file_size"
t.datetime "image_updated_at"
t.integer "author_id"
end
create_table "users", force: :cascade do |t|
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.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"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
From application_controller.rb
def access_denied(exception)
respond_to do |format|
format.json { head :forbidden, content_type: 'text/html' }
format.html { redirect_to main_app.root_url, notice: exception.message }
end
end
EDIT
I thought for a while that the code suggested by #mrzasa would bring a solution as I had no more alert. This was because of my ability.rb :
if user.present?
if user.admin?
puts 'hey admin'
can :manage, :all
end
can :read, all
can :manage, Post, :author_id => user.id
puts 'hey user'
end
If I comment # if user.present? the alert undefined method 'admin?'comes back again. A proof that user.present works, but here to say that there is no user, until I log in outside of the admin panel as a user and then I can see the puts in the console. But I can't perform any action, unless I state can :manage, :all to ANY user.
At this stage, I've added user ||= User.new to create an instance of user before checking for an admin. Even if I allow any visitor to log in as an admin, user.admin? is never verified, unless I set def admin? to true in user.rb
I see that many people using Cancancan define roles instead. Maybe I should go for it...
EDIT 2
It works! I worked on it again from the install of Cancancan to the point where I was with the additions of #mrzasa. This time, active admin understands admin? from the class AdminUser which was not the case yesterday. The beautiful thing is that I did not change any line of code, except commenting # user ||= User.new to get the expected results.
It seems that you have two separate models - one for regular users (users table) and another one for admin (admin_users table). You can add admin? method to both of them - for users returning false and for admin - true.
class User < ApplicationRecord
# ...
def admin?
false
end
end
class AdminUser < ApplicationRecord
# ...
def admin?
true
end
end

Seeding SQLite with Devise Model Gives Uniqueness Constraint Error

Edit
Really Stupid Mistake:
db:reset seeds the database.
I'm trying to seed a db and create users who have posts but the users keep violating the uniqueness constraint...even if there's only one of them.
At the moment, I have no model validations.
The standard User Devise schema:
create_table "users", force: :cascade do |t|
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.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"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "username"
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
db/seeds.rb
1.times do |n|
email = Faker::Internet.email
username = Faker::Name.name
password = 'password'
password_confirmation = 'password'
reset_password_token = nil
id = n
User.create!(
email: email,
username: username,
password: password,
password_confirmation: password_confirmation,
reset_password_token: reset_password_token,
id: id
)
end
I have run the following:
rails c
rake db:reset
rake db:migrate
rake db:seed
>> ActiveRecord::RecordNotUnique: SQLite3::ConstraintException: UNIQUE constraint failed: users.id: INSERT INTO "users"
I have only a single user that is generated but violates the uniqueness. The stack trace tells me it is a problem with the create method but I'm not sure how to remedy this.
I only have two possible things that need to be unique at the db level and that's the index_users_on_email and index_users_on_reset_password both of which are unique if the db has been reset and seeded with only one record.
Where am I going wrong?
Here is how I created my seed for Users, hope it helps.
1.times do
user = User.new(
name: Faker::Name.name,
email: Faker::Internet.email,
password: Faker::Lorem.characters(10)
)
user.skip_confirmation!
user.save!
end
users = User.all

Resources