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

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).

Related

Rails: Uninitialized constant User::VALID_EMAIL_REGEX

Background - I am working with rails version 5.1.2. I am using Cloud 9 IDE. My problem relates to Ch 11 Rails Tutorial by Michael Hartl.
Problem details - typing $ rails test:mailers:
Error:
UserMailerTest#test_account_activation:
NameError: uninitialized constant User::VALID_EMAIL_REGEX
app/models/user.rb:6:in <class:User>'
app/models/user.rb:1:in'
bin/rails test test/mailers/user_mailer_test.rb:5
app/models/user.rb:1 - app/models/user.rb:6:
class User < ApplicationRecord
attr_accessor :remember_token, :activation_token
before_save :downcase_email
before_create :create_activation_digest
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, presence: true, length: { minimum: 6 }, allow_nil: true
Looks like you are missing the regex in your User model
class User < ApplicationsRecord
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
...
end
Just to add to Antarr Byrd's answer.
I had a similar experience when working on a Rails Application.
The issue was that I was defining the REGEX constant below the point of validation call.
That is, instead of this:
class User < ApplicationRecord
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
end
Do this rather:
class User < ApplicationRecord
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX }
end
That's all.
I hope this helps

Uniqueness validation for polymorphic model fails

So I have this really weird problem. Here is my model:
class Clip < ApplicationRecord
belongs_to :owner, polymorphic: true
default_scope -> { order(created_at: :desc) }
validates :address, presence: true, uniqueness: { scope: [:owner_type, :owner_id] }
before_save { self.adress=adress.split("=").last }
validates :owner, presence: true
end
and the test
test "invalid creations" do
get new_clip_path
assert_no_difference "Clip.count" do
post clips_path, params: { clip: { address: "",
description: "bum bum bum" } }
end
assert_template "clips/new"
assert_match "blank", response.body
assert_no_difference "Clip.count" do
#clip allready in db, should refure
post clips_path, params: { clip: { address: "fWNaR-rxAic",
description: "bum bum bum" } }
end
assert_template "clips/new"
assert_no_match "blank", response.body
assert_match "Address has already been taken", response.body
end
The test is passing without a problem but I just realized by accident, that I can still create clips with the same address and owner, as often as I want to. This confuses me for two reasons: a) what is wrong with this line validates :address, presence: true, uniqueness: { scope: [:owner_type, :owner_id] } and b) why does the test not fail?

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

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

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' }

Unable to create correct Mongoid model from JSON

I'm trying to create a Mongoid model from the corresponding JSON structure.
However it does not include the embedded relation frameworks.
I'm using Mongoid 4.0. Am I doing something wrong or is this a bug?
If I store any embedded relation via store_as under a different name than the default serialization, it works as expected. Also, if I create the model in the database from JSON rather than initialize it everything's fine...
JSON input
{
"name": "MyName",
"frameworks": [
{
"name": "grails",
"runtime": "groovy",
"versions": []
}
]
}
Models
require 'mongoid'
class Vendor
include Mongoid::Document
include Mongoid::Attributes::Dynamic
# fields
field :name, type: String
# relations
embeds_many :frameworks
# validations
validates :name, presence: true
validates :frameworks, presence: true
end
class Framework
include Mongoid::Document
embedded_in :vendor
field :name, type: String
field :runtime, type: String
field :versions, type: Array
# validations
validates :name, presence: true
validates :runtime, presence: true
end
Test App
require 'json'
require 'require_relative'
require_relative 'vendor'
begin
json = JSON.parse(File.read('input.json'))
#profile = Vendor.new(json)
puts #profile.inspect
rescue JSON::ParserError => e
puts "Error: " << e.to_s
end

Resources