ActiveRecord: Column 'nivelAcceso' cannot be null - mysql

I need to add a 'Change password' feature to the app I'm currently building, but when I try to change an user's password, I get the following error:
Column 'nivelAcceso' cannot be null; While the user's password and 'nivelAcceso' (the access the user has in the application) are found on the same table (usuarios) they aren't related in any way.
The route that handles the password change looks like this:
app.rb
put '/:id' do
change_password(params[:id], params[:password], params[:confirm])
end
While the controller looks like:
password_controller.rb
def change_password(id, password, confirm)
if password.nil? || confirm.nil?
redirect '/dashboard/change_password', error: 'Debe completar todos los campos.'
elsif password != confirm
redirect '/dashboard/change_password', error: 'Los campos no coinciden.'
else
u = User.find(id)
new_password = BCrypt::Password.create(password)
u.passwordUsuario = new_password
if u.save
redirect '/dashboard/change_password', notice: 'Cambio de contraseƱa exitoso.'
else
redirect '/dashboard/change_password', error: 'Ha ocurrido un error, intente nuevamente.'
end
end
end
I have tried the following with no avail so far:
u.nivelAcceso = session[:rol] # 'nivelAcceso' value is stored in the session

ActiveRecord says the column can't be null. This is usually due to the database being configured this way.
If you configured the database using ActiveRecord migrations, look for something like this:
create_table(:cars) do |t|
# other commands
t.string :foo, null: false
end
You can change this by writing and running a new migration:
change_column :table_name, :foo_column, :string, null: true

Turns out the route to change the password is exactly the same as the route to edit an user.
Original, non-working route:
put '/:id' do
change_password(params[:id], params[:password], params[:confirm])
end
Edited, working route:
put '/change_password/:id' do
change_password(params[:id], params[:password], params[:confirm])
end

Related

How to check if the current user from devise has a certain attribute set

For this website I am using devise to create user profiles. Some users have special permission attributes. In this case db_admin_status is a Boolean attribute. If the user has this set to True, then I want certain nav-links to appear on the page.
This is what the user model looks like
Table name: users
#
# id :bigint not null, primary key
# db_admin_status :boolean
# email :string default(""), not null
# encrypted_password :string default(""), not null
# name :string
# remember_created_at :datetime
# reset_password_sent_at :datetime
# reset_password_token :string
# user_name :string
# created_at :datetime not null
# updated_at :datetime not null
For this rails project I am using application.html.erb and Bootstrap. So in my collapse-nav bar I have embedded in other if statements (that do work) this:
<%if current_user.db_admin_status == 'true'%>
<!--- links appear on nav bar-->
<%end%>
However even when my current user im signed in as has the attribute set to true, the links still don't show up
Step 1.)
You don't need to use any comparisons in the conditional statement as a boolean variable will just result to true/false by itself.
Simply doing
<% if current_user.db_admin_status %>
// your code
<% end
should suffice.
Step 2.)
You could run into trouble when the value of db_admin_status is nill (has not been set yet). You can fix this by defaulting the field to false in your database schema:
Run the following command to create a rails migration to update the db_admin_status field to default to false.
rails g migration DefaultDbAdminStatusToFalseOnUser
This should create a file db/migrate/20130201121110_default_db_admin_status_to_false_on_user.rb
class DefaultDbAdminStatusToFalseOnUser < ActiveRecord::Migration
def change
// your changes go here
end
end
Modify this file to update your field on the user table.
change_column :users, :db_admin_status, :boolean, :default => false
And then finally migrate your changes by running:
rake db:migrate
You want to compare your attribute as boolean and not string.
current_user.db_admin_status == true
Although i would create a helper method which would check if user is eligible to show link and call that method from your view.
def should_show_some_link?
current_user.db_admin_status? #which will return true or false
end
Also your column db_admin_status is not set to default, is that what you want? When the new user creates the value will be nil and not false.

Is it possible to bypass sql_color in Rails active record logs?

I have an issue where a binary representaiton of an IPv6 address will cause the sql_color in active record logs to generate a very long error message.
The query does work and does return expected results.
I think this is because it the binary IPv6 looks like:
"\xFE\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\f"
And the sql_color method is interpreting that as control codes.
If I set:
Rails.applicaiton.config.colorize_logging = false
It still does it even though there is no longer any color being shown.
Ideally I would like to know the best way to bypass sql_color.
Right now I have just overridden the method and put it in a begin/rescue block.
How to reproduce:
rails new binary_bug -d mysql
cd binary_bug
rails db:create
rails g model Bug name:text first_ip:binary second_ip:binary
Update the migration to
class CreateBugs < ActiveRecord::Migration[5.2]
def change
create_table :bugs do |t|
t.text :name
t.binary :first_ip, limit: 16
t.binary :second_ip, limit: 16
t.timestamps
end
end
end
rails db:migrate
Bug.create(name: 'test1', first_ip: IPAddr.new('fe80::c').hton, second_ip: IPAddr.new('fe80::c').hton.to_s )
Bug.create(name: 'test2', first_ip: IPAddr.new('2001:db8:1234::').hton, second_ip: IPAddr.new('2001:db8:1234:ffff:ffff:ffff:ffff:ffff').hton.to_s )
# Try to search the DB.
bugs = Bug.where("first_ip > ?", IPAddr.new('2001:db8:1234::12').hton)
This will give a very long error that starts with:
Could not log "sql.active_record" event. ArgumentError: invalid byte sequence in UTF-8
The first file it points towards is:
gems/activerecord-5.2.2/lib/active_record/log_subscriber.rb:71:in `sql_color'"
Which is a private method and looks like this:
def sql_color(sql)
case sql
when /\A\s*rollback/mi
RED
when /select .*for update/mi, /\A\s*lock/mi
WHITE
when /\A\s*select/i
BLUE
when /\A\s*insert/i
GREEN
when /\A\s*update/i
YELLOW
when /\A\s*delete/i
RED
when /transaction\s*\Z/i
CYAN
else
MAGENTA
end
end
If I replace that with just MAGENTA or wrap it in a begin/rescue block and restart spring it will work fine.

Datamapper not saving records to MySQL

Datamapper isn't saving my user models.
(This is a Sinatra webapp and the db is an AWS RDS mysql db.)
The User model:
class User
include DataMapper::Resource
property :uid, Serial
property :user, String, :key => true, :length => 3..20
property :pass, String, :required => true, :length => 6..50
end
The code to set it:
post "/register" do
username = params["username"]
password = params["password"]
begin
encrypted_password = BCrypt::Password.create password
meme = User.new :user => username, :pass => encrypted_password
meme.save
raise DatabaseError, "User record not saved" unless meme.saved?
flash[:register] = "Welcome, new user! Please log in now."
redirect "/login"
# disabled rescue stuff...
end
end
(if you want, test it yourself at dittoslash.uk)
(can i do this on stack overflow? edit this out if you can't)
EDIT: Updated validation rules. Now I'm getting an error of 'Pass must be between 6 and 50 characters long' (with a 28 (or 30?) character password)
max pleaner answered this for me.
For Googlers looking for answers:
check your validations, and make sure that encryption dosen't make the password longer than your maximum.

Fetch data from a database in rails

I have created a rail application
i am connecting to mysql database
i already have 2 tables users and history
how can i fetch data from these tables
i can save data to database
with
def register
if(params[:register])
#registermsg=Users.where(:username=>params[:register][:username])
if #registermsg.length>0
flash[:success] = "Username exists:#{params[:username]}:"
else
#reg = Users.create(user_params)
#reg.save
flash[:success] = "success:#{params[:register][:username]}:"
end
end
end
def user_params
params.require(:register).permit(:username, :password, :password2)
end
but when i am fetching data from users
def login
if session[:user]
redirect_to '/dash'
end
if(params[:login])
#login1=Users.where("username=? AND password=?",params[:login][:username],params[:login][:password])
if #login1.length==1
session[:user] = #login1
hist = History.create(userid: **#login1.id**, ip: request.remote_ip )
// here #login1.id is giving me error
redirect_to '/dash'
else
flash[:success] = "Wrong"
end
end
end
#login1=Users.where("username=? AND password=?",params[:login][:username],params[:login][:password])
#login1.to_yaml is printing full data
how can i get id,username etc from #login1
presently #login1.id is getting error
I researched in many websites including stack overflow till now i didnt got any solution please help
Here #login1 is an ActiveRelation object. You will have to call first to get the actual user object
if #login1.count==1
session[:user] = #login1.first
hist = History.create(userid: #login1.first.id, ip: request.remote_ip )
redirect_to '/dash'

Rspec: Carrierwave doesn't save file from spec/fixtures

I have my Report model:
class Report < ActiveRecord::Base
belongs_to :user
attr_accessible :ready_status, :document
mount_uploader :document, DocumentUploader
def attach( report_file )
self.update_attributes( :document => File.open( report_file ), :ready_status => true )
end
end
This model has attach metod, which i use to save document and other param. Now i want to test that this function works.
/spec/models/report_spec.rb
# encoding: utf-8
require 'spec_helper'
describe Report do
before(:each) do
#user = User.make!
end
...
context "File's saving" do
before(:each) do
#report = #user.reports.create
#csv_report_file = "#{Rails.root}/spec/files/report.csv"
end
it "CSV should be saved" do
csv_report_filename = #csv_report_file.split("/").last
#report.attach #csv_report_file
#report.reload
#report.document.file.filename.should == csv_report_filename
end
end
end
When i try to saving file from /spec/files i get such error:
Report File's saving CSV should be saved
Failure/Error: #report.document.file.filename.should == csv_report_filename
NoMethodError:
undefined method `filename' for nil:NilClass
But when i try another file from another folder (for example "#{Rails.root}/samples/my-report.csv") then my test passes.
How can i fix that?
Oh, i found the answer. Carrierwave doesn't save empty file and i had one. When i added some data in the file (/spec/files/report.csv) my problem has gone.