Unable to configure cancancan in Rails - ruby-on-rails

I am using active_admin and cancancan gem.
ability.rb
if user.admin?
can :manage, :all
elsif user.regular?
can :read, :all
else
can :read, :all
end
I have role column in database. It is basically a blog.
schema.rb
ActiveRecord::Schema.define(version: 2019_02_18_221247) 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 "categories", force: :cascade do |t|
t.string "category"
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.integer "user_id"
t.date "published_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "category_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.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "role"
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
user.rb
class User < ApplicationRecord
has_many :posts
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable,
:recoverable, :rememberable, :validatable
def admin?
role == "admin"
end
def regular?
role == "regular"
end
def guest?
role == "guest"
end
end
Goal
My goal is to not allow a guest user to create a new Post.
Problem
The problem I am getting access denied for both admin and guest user though I have clearly defined what different types of user can do in ability.rb.
If you need more info about the code you can check it on github.
Thank you in advance.

The problem is that you are overriding the user that's passed to the Ability class. Remove this line:
user = User.new(role: "guest")

Related

How would i create an instance of a object after a user creates their account using devise

As of right now i have the user model from the Devise gem, and i have also created a Player model to store information that i need for my app. All I'm trying to do is make a new Player whenever a User creates an account. The Player model has 3 columns - one for the user_id, one for the game_id and one for the deck_id.
#schema.rb
create_table "games", force: :cascade do |t|
t.text "players"
t.integer "player_count"
t.boolean "rogue", default: true
t.boolean "wizard", default: true
t.boolean "paladin", default: true
t.boolean "barbarian", default: true
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "last_selected_deck"
end
create_table "players", force: :cascade do |t|
t.integer "user_id", null: false
t.integer "game_id"
t.integer "company_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["company_id"], name: "index_players_on_company_id"
t.index ["game_id"], name: "index_players_on_game_id"
t.index ["user_id", "game_id"], name: "index_players_on_user_id_and_game_id", unique: true
t.index ["user_id"], name: "index_players_on_user_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.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "company_id", null: false
t.string "username"
t.integer "game_id"
t.index ["company_id"], name: "index_users_on_company_id"
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
#user.rb
class User < ApplicationRecord
after_create :create_player
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
belongs_to :company
has_one :player, dependent: :destroy
has_one :game, through: :player
def create_player
#code
end
end
i thought i could create a method inside the user.rb model that should be executed after creation, but it doesn't seem to work
You have declared the user-player association, so you can do something like this:
def create_player
self.player.create!
# Player.create!(user_id: self.id) # without taking account assiciation
end
Hope it helps!

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

My sqlite database is not able to persist anything?

I have a Rails Api with models, controllers, and serializers. The database is set up, and I have made several migrations, all of which have resulted in corresponding changes to the schema. However, nothing is being persisted to the database, either in the rails console or from the seed data. For instance, when I try to run User.create in the console, I see this message appear:
2.3.3 :003 > User.create
(0.1ms) begin transaction
(0.1ms) rollback transaction
=> #<User id: nil, email: "", created_at: nil, updated_at: nil>
Similarly, I have this data in my seeds file:
users = User.create([{ email: 'adam#adam.com' }, { email: 'ryan#ryan.com'
}])
BankAccount.create(name: 'Adams Chase Checking Account', user_id: users.first)
When I run rake db:seed and attempt to call User.all or BankAccount.all in the rails console, I am given an empty array in both cases. I have heard of errors like this being caused by unmet validations on the models, but my models do not have any validations. I am at a loss as to what could be causing this issue. Any help is greatly appreciated! Also, for what it's worth, this project uses Rails 5.1.4, and I have only used 4.x.x previously. Here is the User model (using devise):
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 :bank_accounts
has_many :credit_cards
has_many :investments
has_many :loans
has_many :assets
has_many :recurring_payments, through: :bank_accounts
has_many :recurring_payments, through: :credit_cards
has_many :recurring_payments, through: :investments
has_many :recurring_payments, through: :loans
end
And here is the bank account model:
class BankAccount < ApplicationRecord
belongs_to :user
has_many :recurring_payments
accepts_nested_attributes_for :recurring_payments
end
Here is the full schema:
ActiveRecord::Schema.define(version: 20180205231948) do
create_table "assets", force: :cascade do |t|
t.string "name"
t.integer "value"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "bank_accounts", force: :cascade do |t|
t.string "name"
t.integer "balance"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "credit_cards", force: :cascade do |t|
t.string "provider"
t.integer "balance"
t.integer "interest_rate"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "investments", force: :cascade do |t|
t.string "name"
t.integer "value"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "loans", force: :cascade do |t|
t.integer "user_id"
t.integer "interest_rate"
t.integer "remaining_balance"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "recurring_payments", force: :cascade do |t|
t.string "source"
t.boolean "status"
t.date "pay_date"
t.integer "pay_amount"
t.integer "duration"
t.integer "bank_account_id"
t.integer "credit_card_id"
t.integer "loan_id"
t.integer "investment_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
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
end
My guess is this.
users = User.create([{ email: 'adam#adam.com' }, { email: 'ryan#ryan.com' }])
Devise validates the default password before saving (6 characters minimum). Try running this command in console and see if it throws any errors?
user = User.create(email: 'adam#adam.com')
user.errors

Rails rollback transaction for bids

Hello I'm getting a rollback transaction when I try to create a Bid from the rails console. These are my models:
Product Model
class Product < ApplicationRecord
belongs_to :user
belongs_to :category
has_many :ratings
has_many :bids
end
Bid model:
class Bid < ApplicationRecord
belongs_to :products
belongs_to :user
end
User model:
class User < ApplicationRecord
has_many :products
has_many :ratings
has_many :bids
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
And this is my schema:
ActiveRecord::Schema.define(version: 20161231124005) do
create_table "bids", force: :cascade do |t|
t.integer "amount"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.integer "product_id"
t.index ["product_id"], name: "index_bids_on_product_id"
t.index ["user_id"], name: "index_bids_on_user_id"
end
create_table "categories", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "products", force: :cascade do |t|
t.string "title"
t.text "description"
t.string "image_url"
t.integer "price"
t.datetime "deadline"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.integer "category_id"
end
create_table "ratings", force: :cascade do |t|
t.integer "rating"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.integer "product_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.string "username"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
t.index ["username"], name: "index_users_on_username", unique: true
end
end
Although I tried to create like so: Bid.create(amount: 500, user_id: 1, product_id:6) it doesn't save because of the rollback transaction.
Thanks in advance
The code you posted doesn't really help. You should also add the logs.
Before posting any logs, I'd try b = Bid.new(amount: 500, user_id: 1, product_id: 6) and b.save in the console. After that, do b.errors and see what's causing the rollback.
EDIT: Add .save.
EEDIT: For anyone experiencing the same problem, the issue was with the Bid model referencing a Product wrong.
When using belongs_to, the model should be singular, not plural. Ex: belongs_to: apple not belongs_to: apples

Matching users Ruby on Rails and ActiveRecord

[question solved] => I just made a silly mistake and forgot to add #match.save at the end of my method :)
I'm relatively new to RoR and the ActiveRecord architecture. I'm trying to build a simple app that can match 2 users together based on their interests. First here's the schema of my database:
Link to my DB's schema
or if you prefer here's the schema.rb file:
ActiveRecord::Schema.define(version: 20160612080318) do
create_table "conversations", force: :cascade do |t|
t.integer "user1_id"
t.integer "user2_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "conversations", ["user1_id"], name: "index_conversations_on_user1_id", using: :btree
add_index "conversations", ["user2_id"], name: "index_conversations_on_user2_id", using: :btree
create_table "interests", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "matches", force: :cascade do |t|
t.integer "user1_id"
t.integer "user2_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "matches", ["user1_id"], name: "index_matches_on_user1_id", using: :btree
add_index "matches", ["user2_id"], name: "index_matches_on_user2_id", using: :btree
create_table "messages", force: :cascade do |t|
t.text "content"
t.integer "conversation_id"
t.integer "user_id"
t.datetime "read_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "messages", ["conversation_id"], name: "index_messages_on_conversation_id", using: :btree
add_index "messages", ["user_id"], name: "index_messages_on_user_id", using: :btree
create_table "user_interests", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.integer "interest_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.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "first_name"
t.string "last_name"
t.integer "age"
t.string "avatar_url"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
add_foreign_key "messages", "conversations"
add_foreign_key "messages", "users"
add_foreign_key "user_interests", "interests"
add_foreign_key "user_interests", "users"
end
Just to test my models I didn't take into account the algorithm that will match users based on their interest. So here's my matches_controller.rb:
class MatchesController < ApplicationController
def new
#match = Match.new
end
def create
#match = Match.new(match_params)
#match.user1_id = current_user.id
#match.user2_id = User.first.id
end
private
def match_params
params.require(:match).permit(:user1_id, :user2_id)
end
end
my match model:
class Match < ActiveRecord::Base
belongs_to :user1, class_name: "User"
belongs_to :user2, class_name: "User"
end
and finally my user model:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :user_interests, dependent: :destroy
has_many :interests, through: :user_interests, dependent: :destroy
has_many :messages, dependent: :destroy
has_many :matches, dependent: :destroy
def conversations
Conversation.includes(:messages)
.where("user1_id = :id OR user2_id = :id", id: id)
.order("messages.created_at DESC")
end
def other_user(conversation)
conversation.users.include?(self) ? conversation.other_user(self) : nil
end
def unread_conversations
conversations.select { |c| c.unread_messages?(self) }
end
def unread_conversations_count
unread_conversations.count
end
def unread_conversations?
unread_conversations_count > 0
end
def one_avatar_url
avatar_url ? avatar_url : "http://placehold.it/64x64"
end
end
I've tried to test my Match.create method in the console but got only nil for user1_id and user2_id. I've been looking all day long everywhere without being able to pinpoint what's wrong with my code.
Thanks a lot for helping me on this issue :)

Resources