How can i return some message if before_validation method is false by Sinatra - ruby

I want to return some message that tell the user their password is not match with the confirm password field.
This is my code
post '/signup' do
user = User.new(params[:user])
if user.create_user
"#{user.list}"
else
"password not match"
end
end
require 'bcrypt'
class User < ActiveRecord::Base
include BCrypt
# This is Sinatra! Remember to create a migration!
attr_accessor :password
validates :username, presence: true, uniqueness: true
validates :email, :format => { :with => /\A[\w+\-.]+#[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i ,
:message => "Email wrong format" }
validates :email, uniqueness: true,presence: true
validates :encrypted_password, presence: true
validates :encrypted_password, length: { minimum: 6 }
before_validation :checking_confirm_password
def initialize(signup = {})
##signup = signup
super()
#username = signup["username"]
#email = signup["email"]
#password = signup["password"]
#confirm_password = signup["confirm_password"]
end
def create_user
p_p = Password.create(#password)
p_h ||= Password.new(p_p)
user_hash = {:username => #username,:email => #email, :encrypted_password => p_h}
return User.create(user_hash)
end
def list
User.all
end
private
def checking_confirm_password
if #password != #confirm_password
return false
end
end
end
So how can i specific the message that will send back to the user,
if their password is not match or the validation fail before create the dada?
Thanks!

The validations populate #user.errors with all validation errors with all validation errors by field, so you can easily return all validation errors at once like so:
post '/signup' do
user = User.new(params[:user])
if user.create_user
"#{user.list}"
else
user.errors.full_messages
end
end
Have a look at: http://edgeguides.rubyonrails.org/active_record_validations.html#working-with-validation-errors

Related

Can't Use Validates Presence On Picture Rails 5.x

micropost.rb
class Micropost < ActiveRecord::Base
belongs_to :user
default_scope -> { order(created_at: :desc) }
mount_uploader :picture, PictureUploader
validates :user_id, presence: true
validates :tag1, presence: true, length: { maximum: 20 }
validates :tag2, presence: true, length: { maximum: 20 }
validates :tag3, presence: true, length: { maximum: 20 }
validates :picture, presence: true
validate :picture_size
validates :ispublic, inclusion: { in: [ true, false ] }
private
# Validates the size of an uploaded picture.
def picture_size
if picture.size > 5.megabytes
errors.add(:picture, "should be less than 5MB in size.")
end
end
end
microposts_controller.rb snippet:
def create
#micropost = current_user.microposts.build(micropost_params)
if #micropost.save!
flash[:success] = "Post created!"
redirect_to root_url
else
#feed_items = []
render 'static_pages/home'
end
end
def micropost_params
params.require(:micropost).permit(:tag1, :tag2, :tag3, :picture, :ispublic)
end
Test that is failing snippet:
tag1 = "This"
tag2 = "Is"
tag3 = "Sparta"
image = File.open("test/fixtures/p_avatar.png")
assert_difference 'Micropost.count', 1 do
post microposts_path, params: {micropost: { tag1: tag1, tag2: tag2, tag3: tag3, picture: "image",
ispublic: false }}
end
Test error:
Validation failed. Picture can't be blank.
I am using CarrierWave...based on other answers I was wondering if I can't use the presence: true validation with a picture, but I thought the #micropost.save would just store whatever as a string (varchar). For testing purposes, I just want to make sure a valid string is passed, but maybe that isn't even necessary if CarrierWave and picture_size validation is enough.
Found it. In the Rails spec, there is a function called fixture_file_upload() which does all the heavy lifting of creating the image object for me (some sort of upload to a cache it seems) and making the Model.save() method validate it and store the string in the db.
Thanks to this site it informed me a bit on image upload testing without going through FactoryBot: https://jeffkreeftmeijer.com/carrierwave-rails-test-fixtures/
Ultimately I decided I micropost doesn't require a picture (A la Twitter).

Validation doesn't work in "sexy" style

It seems that Rails doens't let me pass in more than one parameter when using this validation syntax. It always has a syntax method for an unexpected comma after the first argument.
class Apartment < ActiveRecord::Base
geocoded_by :location
after_validation :geocode
has_many :image_attachments
validates_associated :image_attachments
accepts_nested_attributes_for :image_attachments
validates :location, presence: true
validates :description, presence: true
validates :price, :presence => true
,:format => { with: /^[0-9]+$/, message: 'must be a number' }
validates :longitude, presence: true
end
It's bad formatting (and very "unsexy") to have the comma at the beginning of the next line.
Better to do...
validates :price, :presence => true,
:format => { with: /^[0-9]+$/, message: 'must be a number' }
...which should work fine.
A more consistent style is to use the Ruby 1.9 convention for key/value when key is a symbol.
validates :price, presence: true,
format: { with: /^[0-9]+$/, message: 'must be a number' }

Ruby on Rails : Tricky Many to Many relationship does not work

I am designing a "Lists" mapping feature in my application for transcoding purposes.
So that my mappins_list object points to a source_list object and a target_list object, both being of an instance values_list class.
The design looks classical, but it does not behave as expected:
<td><%= link_to #mappings_list.source_list.name, #mappings_list.source_list%>
raises a
undefined method `source_list' for #<ActiveRecord::Relation::ActiveRecord_Relation_MappingsList:0x00000004217718>
in the index view.
(note that one record was crated with correct attributes, it should be displayed there)
Here is the code:
# == Schema Information
#
# Table name: values_lists
#
# id :integer not null, primary key
# playground_id :integer
# code :string(255)
# name :string(255)
# description :text
# created_by :string(255)
# updated_by :string(255)
# owner_id :integer
# table_name :string(255)
# created_at :datetime
# updated_at :datetime
# software_id :integer
# software_name :string(255)
#
class ValuesList < ActiveRecord::Base
### scope
scope :pgnd, ->(my_pgnd) { where "playground_id=?", my_pgnd }
### before filter
before_create :set_code
### validation
validates :code, length: { maximum: 100 }
validates :name, presence: true, uniqueness: true, length: { maximum: 100 }
validates :description, length: { maximum: 1000 }
validates :created_by , presence: true
validates :updated_by, presence: true
validates :playground_id, presence: true
belongs_to :playground
validates :playground, presence: true # validates that the playground exists
belongs_to :owner, :class_name => "User", :foreign_key => "owner_id" # helps retrieving the owner name
belongs_to :software, :class_name => "Parameter", :foreign_key => "software_id" # helps retrieving the software name
has_many :values
has_many :mappings_lists
### private functions definitions
private
### before filters
def set_code
self.code = name.gsub(/[^0-9A-Za-z]/, '_').upcase
end
end
.
# == Schema Information
#
# Table name: mappings_lists
#
# id :integer not null, primary key
# playground_id :integer
# code :string(255)
# name :string(255)
# description :text
# created_by :string(255)
# updated_by :string(255)
# owner_id :integer
# source_list_id :integer
# target_list_id :integer
# created_at :datetime
# updated_at :datetime
#
class MappingsList < ActiveRecord::Base
### scope
scope :pgnd, ->(my_pgnd) { where "playground_id=?", my_pgnd }
### before filter
before_create :set_code
### validation
validates :name, presence: true, uniqueness: true, length: { maximum: 100 }
validates :description, length: { maximum: 1000 }
validates :created_by , presence: true
validates :updated_by, presence: true
validates :playground_id, presence: true
belongs_to :playground
validates :playground, presence: true # validates that the playground exists
belongs_to :owner, :class_name => "User", :foreign_key => "owner_id" # helps retrieving the owner name
belongs_to :source_list, :class_name => "ValuesList", :foreign_key => "source_list_id" # helps retrieving the source list name
belongs_to :target_list, :class_name => "ValuesList", :foreign_key => "target_list_id" # helps retrieving the target list name
has_many :mappings
### private functions definitions
private
### before filters
def set_code
self.code = "#{source_list.code}_TO_#{target_list.code}"
end
end
routes contains this:
resources :values_lists do
resources :values
resources :mappings_lists
end
The controller is here:
class MappingsListsController < ApplicationController
# Check for active session
before_action :signed_in_user
# Retrieve current current mapping
before_action :set_mappings_list, only: [:show, :edit, :update, :destroy]
# Retrieve all lists of values
before_action :set_values_lists
# GET /mappings_list
# GET /mappings_list.json
def index
#mappings_list = MappingsList.pgnd(current_playground).order("name")
end
# GET /mappings_list/1
# GET /mappings_list/1.json
def show
### Retrieved by Callback function
end
# GET /mappings_list/new
def new
#mappings_list = MappingsList.new
end
# GET /mappings_list/1/edit
def edit
### Retrieved by Callback function
end
# POST /mappings_list
# POST /mappings_list.json
def create
#mappings_list = MappingsList.new(mappings_list_params)
#mappings_list.updated_by = current_user.login
#mappings_list.created_by = current_user.login
#mappings_list.playground_id = current_user.current_playground_id
#mappings_list.owner_id = current_user.id
respond_to do |format|
if #mappings_list.save
format.html { redirect_to #mappings_list, notice: 'List of mappings was successfully created.' }
format.json { render action: 'show', status: :created, location: #mappings_list }
else
format.html { render action: 'new' }
format.json { render json: #mappings_list.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /mappings_list/1
# PATCH/PUT /mappings_list/1.json
def update
### Retrieved by Callback function
#mappings_list.updated_by = current_user.login
respond_to do |format|
if #mappings_list.update(mappings_list_params)
format.html { redirect_to #mappings_list, notice: 'List of mappings was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #mappings_list.errors, status: :unprocessable_entity }
end
end
end
# DELETE /mappings_list/1
# DELETE /mappings_list/1.json
def destroy
### Retrieved by Callback function
#mappings_list.destroy
respond_to do |format|
format.html { redirect_to mappings_lists_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
# Check for active session
def signed_in_user
redirect_to signin_url, notice: "You must log in to access this page." unless signed_in?
end
def set_mappings_list
#mappings_list = MappingsList.pgnd(current_playground).find(params[:id])
end
# retrieve the list of values lists
def set_values_lists
#lists_of_values = ValuesList.all
end
# Never trust mappings from the scary internet, only allow the white list through.
def mappings_list_params
params.require(:mappings_list).permit(:name, :description, :source_list_id, :target_list_id)
end
end
Would the double reference to values_list turn my application into trouble ?
Thanks for your help,
Best regards,
Fred
In the class MappingsList < ActiveRecord::Base model
you have MappingList belonging to source_list.
which I believe is backwards:
class Order < ActiveRecord::Base
belongs_to :customer
end
#order = #customer.orders
OK, I got it !!!
In the index view, I cannot refer to one instance variable such as #mappings_list as I work on a list of instances.
The code works fine with :
<td><%= link_to mappings_list.source_list.name, mappings_list.source_list%>
Being a beginner at RoR, I hope my interpretation is right ...
Thanks for your help,
Best regards,
Fred

When is the validator of email uniqueness trigerred?

I have a question about this test from the Michael Hartl tutorial :
Model:
class User < ActiveRecord::Base
.
.
.
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: true
end
Test:
require 'spec_helper'
describe User do
before do
#user = User.new(name: "Example User", email: "user#example.com")
end
.
.
.
describe "when email address is already taken" do
before do
user_with_same_email = #user.dup
user_with_same_email.email = #user.email.upcase
user_with_same_email.save
end
it { should_not be_valid }
end
end
My understanding of the uniqueness validator for the email is that it cannot be added twice in the database. But in this test, the User is just instantiated with a new, not a create.
So here is what I think happens:
#user = User.new (just in memory)
...
user_with_same_email = #user.dup we have two users in memory
...
user_with_same_email.save we are inserting the first user in the db, so it should be valid, and yet the test it { should_not be_valid } passes.
What am I getting wrong ?
What really happens:
In before:
#user = User.new (just in memory)
In the describe:
user_with_same_email = #user.dup we have two users in memory
user_with_same_email.save we are inserting the first user in the db, so it should be valid, and it is ! But that's not what's being tested here
In the it:
should_not be_valid calls .valid? on #user, and since we've just inserted an user with the same email, #user is not valid. And so the test passes.

Rails -- before_save not working?

I am following Michael Hartl's RoR tutorial, and it is covering the basics of password encryption. This is the User model as it currently stands:
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :name, :email,: password, :password_confirmation
email_regex = /^[A-Za-z0-9._+-]+#[A-Za-z0-9._-]+\.[A-Za-z0-9._-]+[A-Za-z]$/
#tests for valid email addresses.
validates :name, :presence => true,
:length => {:maximum => 50}
validates :email, :presence => true,
:format => {:with => email_regex},
:uniqueness => {:case_sensitive => false}
validates :password, :presence => true,
:length => {:maximum => 20, :minimum => 6},
:confirmation => true
before_save :encrypt_password
private
def encrypt_password
#encrypted_password = encrypt(password)
end
def encrypt(string)
string
end
end
(Obviously this isn't doing any encrypting because the encrypt method isn't really implemented but that's not my question)
I then wrote the following Spec (according to the tutorial):
require 'spec_helper'
describe User do
before(:each) do
#attr = { :name => "Example User", :email => "user#example.com",
:password => "abc123", :password_confirmation => "abc123"}
end
describe "password encryption" do
before(:each) do
#user = User.create!(#attr) # we are going to need a valid user in order
# for these tests to run.
end
it "should have an encrypted password attribute" do
#user.should respond_to(:encrypted_password)
end
it "should set the encrypted password upon user creation" do
#user.encrypted_password.should_not be_blank
end
end
end
The first of these tests passes, but since #user.encrypted_password is nil, the second test fails. But I don't understand why it's nil since the encrypt_password method should be being called by before_save. I know I must be missing something -- can someone please explain?
The encrypt_password method is incorrect, it should read:
def encrypt_password
self.encrypted_password = encrypt(password)
end
Note the use of self, which will properly set the attribute for the user object rather than creating an instance variable which is forgotten.
This is an old question and this is more of a comment but I don't have enough reputation to comment yet. Just wanted to link this question too as it goes into some solid detail about self.
Why isn't self always needed in ruby / rails / activerecord?

Resources