Datamapper not saving records to MySQL - 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.

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.

ActiveRecord: Column 'nivelAcceso' cannot be null

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

Encoding latin1 to UTF8 in Rails

I have a legacy MySQL database with latin1 encoding, and new MySQL database with utf-8 encoding. When I migrate the data from the legacy to new one, the strings returned and rendered in webpages contains weird characters.
example: â¥Chocolate biscuitâ¢
There's a model that connects to the old database to get the records, and use a rake task to map the old records and create new records
class LegacyDatabase < ActiveRecord::Base
self.abstract_class = true
establish_connection(
adapter: "mysql2",
database: "old_database",
encoding: "latin1"
)
end
I referred to this website to solve the encoding problems, but the fallback hash is hardcoded. I need a dynamic one so that I don't need to add the fallbacks each time when a loop that fixes encoding is called.
def fix_encoding(str)
# Referring to the solution from the website
new_str = str.encode('cp1252',:fallback => {
"\u0080" => "\x80".force_encoding("cp1252"),
"\u0081" => "\x81".force_encoding("cp1252"),
"\u008D" => "\x8D".force_encoding("cp1252"),
"\u008F" => "\x8F".force_encoding("cp1252"),
"\u0090" => "\x90".force_encoding("cp1252"),
"\u009D" => "\x9D".force_encoding("cp1252"),
"\u0098" => "\x98".force_encoding("cp1252"),
"\u0099" => "\x99".force_encoding("cp1252")
}).force_encoding("utf-8")
return new_str
end
I want to change it to be dynamic, but I failed to convert it.
# How to do it in dynamic?
new_str = str.encode('cp1252', :fallback => Proc.new { |v| "#{v[4..5]}".force_encoding("cp1252") }).force_encoding("utf-8")
Or is there any other solution to fix the encoding problem?

Mongoid embedded documents and Rails strong parameters not working

I have a 1-N relationship in Mongoid/Rails:
class Company
include Mongoid::Document
field :name, type: String
embeds_many :people, class_name: 'Person'
end
class Person
include Mongoid::Document
field :first_name, type: String
embedded_in :company, class_name: 'Company', inverse_of: 'people'
end
Now I can successfully create a Company as follows in the console; for example:
> c = Company.new(name: 'GLG', :people => [{first_name: 'Jake'}]) # OK!
> c.people # OK!
Then I have a JSON API controller to update a company, along the lines of:
# PUT /api/companies/:id
def update
if Company.update(company_params)
# ... render JSON
else
# ... render error
end
end
private
def company_params
params.require(:company).permit(:name, :people => [:first_name])
end
Now, when the PUT request comes in from the frontend, the company_params is always missing the :people attribute. Rails log says:
Parameters: {"id"=>"5436fbc64a616b5240050000", "name"=>"GLG", "people"=>[{"first_name"=>"Jake"}], "company"=>{"name"=>"GLG"}}
I don't get an "Unpermitted parameters" warning. I've tried every conceivable way of permitting the people field and it still doesn't get included.
params.require(:company).permit!
Results in the same. What am I doing wrong?
You have to accept nested_attributes on assignment
class Company
include Mongoid::Document
field :name, type: String
embeds_many :people, class_name: 'Person'
accepts_nested_attributes_for :people
end

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.