Rails3/Mongoid Validations Not Running - ruby-on-rails

In my application, it seems that no ActiveModel validations are running, at all. That is, they always return true (valid) no matter how invalid the data actually is.
class QueueItem
include Mongoid::Document
include Mongoid::Timestamps
belongs_to :user
field :appointment_time, type: DateTime, allow_nil: true
field :notes, type: String, allow_nil: true
# field :position, type: Integer, default: 0
validates :user, presence: true, allow_blank: false, allow_nil: false
validates_length_of :notes, :minimum => 2, allow_blank: false
end
Then, when you try to save or validate a record with bad data, this is what you get:
ruby-1.9.2-p290 :028 > QueueItem.validators
=> [#<ActiveModel::Validations::PresenceValidator:0x007f8303adb190 #attributes=[:user], #options={:allow_blank=>false, :allow_nil=>false}>, #<ActiveModel::Validations::LengthValidator:0x007f8303ee5a60 #attributes=[:notes], #options={:minimum=>2, :allow_blank=>false}>]
ruby-1.9.2-p290 :029 > qi = QueueItem.new
=> #<QueueItem _id: 4edf5a0535be359a79000004, _type: nil, created_at: nil, updated_at: nil, user_id: nil, appointment_time: nil, notes: nil, called: false, visited: false, rejected: false>
ruby-1.9.2-p290 :030 > qi.notes = "x"
=> "x"
ruby-1.9.2-p290 :031 > qi.valid?
=> true
It seems that the validations are in fact being registered in the model, as shown by QueueItem.validations. Why, then, do they always return true? This is happening not just in this model, but in all models in my application.
UPDATE
I added a custom validator, and that is successfully firing.
validate :test_validation
def test_validation
logger.info ":test_validation has fired"
self.errors[:base] << "Something is royally screwed!"
end
Now, when I call model.valid?, it returns false, and the logger outputs that message. The custom validator is in fact adding errors to the object, and returning false. Still not clear why the standard ActiveModel ones are not being executed. Is there any way to trace these?

So, turns out that there was a corrupted string in the locals/en.yml file under the errors: section.

Related

Rspec presence: true check fails even though it works as intended

I have the following Rspec test with the following output for my User model in a Rails API I'm building:
RSpec.describe User, type: :model do
let(:michael) { User.new(email: "michael#email.com", password: "Password1", password_confirmation: "Password1") }
it 'is not valid without a password' do
michael.password = ''
expect(michael).not_to be_valid, "Expect User to have a Password"
end
end
1) User basic checks is not valid without a password
Failure/Error: expect(michael).not_to be_valid, "Expect User to have a Password"
Expect User to have a Password
# ./spec/models/user_spec.rb:19:in `block (3 levels) in <main>'
However, for some reason this test just fails, even with the following on my User model
class User < ApplicationRecord
has_secure_password
validates :email, presence: true, uniqueness: true
validates :password, presence: true
validates :password,
format: { with: /\A(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).{8,}\Z/, message: "Password must be at least 8 characters long, contain at least 1 uppercase and 1 lowercase letter and 1 number" },
confirmation: true,
on: :create
end
The above validation works fine, as you can see here:
➜ rails c
Running via Spring preloader in process 2774
Loading development environment (Rails 6.0.3.1)
irb(main):001:0> new = User.new
irb(main):002:0> new.email = "testing#testing.com"
irb(main):003:0> new.save
(0.2ms) BEGIN
User Exists? (0.6ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = $1 LIMIT $2 [["email", "testing#testing.com"], ["LIMIT", 1]]
(0.2ms) ROLLBACK
=> false
irb(main):004:0> new.errors
=> #<ActiveModel::Errors:0x00007f743848dfb0 #base=#<User id: nil, email: "testing#testing.com", password_digest: nil, created_at: nil, updated_at: nil, admin: false>, #messages={:password=>["can't be blank", "can't be blank", "Password must be at least 8 characters long, contain at least 1 uppercase and 1 lowercase letter and 1 number"]}, #details={:password=>[{:error=>:blank}, {:error=>:blank}, {:error=>:invalid, :value=>nil}]}>
What exactly am I doing wrong here for this test to fail? It's a painfully simple one, and all the other ones work as expected except for the password test.
First, in your tests password = '' is a valid one because for Ruby, '' is something. You have to add this to your validation:
validates :password, presence: true, allow_blank: false
Also, take a look, your password validation is for on: :create and in your spec you are not creating it.

Mongoid in rails not saving document

I'm using rails 4.2.5 with mongoid 5.1.0 on windows 10 in dev mode. I have created a model "Signup" but it won't save to MongoDB. I can see that rails connects to MongoDB but no transactions are performned.
What am I missing?
Model code:
class Signup
include Mongoid::Document
field :email, type: String
field :date, type: DateTime, default: ->{ Time.now }
end
Console tests:
irb(main):034:0> s = Signup.create
=> #<Signup _id: 57b9d0436fc5511c04a945ce, email: nil, date: 2016-08-21 16:01:07 UTC>
irb(main):035:0> Signup.count
=> 0
irb(main):036:0> s.save!
=> true
irb(main):037:0> Signup.count
=> 0
irb(main):038:0>
found the solution, I used a dot in the database name in mongoid.yml (project.io) which somehow hindered db creation. I removed it (project_io) and everything is working now as it should.

Why is Rails setting my attribute to nil on create?

Ruby 2.2.0 on Rails 4.2.2
I'm attempting to write a custom date validator (that is going to be expanded to handle some other cases once I get this part working), but right now it's failing to appropriately validate (and return false) on strings - it doesn't even run. It seems that rails is completely ignoring the date_ended value when it's set to a string. When I try the same test except with an integer it correctly validates and fails that validation. If I don't allow nil values, the validator correctly prevents record creation on a string value, but only because it rejects the nil value. Any and all suggestions are appreciated.
The same exact problem exists for date_started.
Edit: I've confirmed that the validation is failing on the second expectation and not the first validation by double-checking that CommitteeMember.count is 0 before the first expectation.
CommitteeMember:
class CommitteeMember < ActiveRecord::Base
belongs_to :committee
belongs_to :member
validates :committee_id, presence: true
validates :member_id, uniqueness: { scope: :committee_id }, presence: true
validates :date_started, date: true, allow_nil: true
validates :date_ended, date: true, allow_nil: true
end
schema.rb relevant lines:
create_table "committee_members", force: :cascade do |t|
t.integer "committee_id", null: false
t.integer "member_id", null: false
t.date "date_started"
t.date "date_ended"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
DateValidator (custom validator):
(note the printed value in the middle)
class DateValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
puts "Validating #{value}"
unless value.kind_of?(Date)
record.errors[attribute] << "must be of type date"
end
end
end
CommiteeMember relevant spec:
(note the printed value in the middle)
it 'should fail with a string for date_ended' do
expect(CommitteeMember.count).to eq(0)
CommitteeMember.create!(member_id: 1, committee_id: 1, date_ended: "S")
ap CommitteeMember.first
expect(CommitteeMember.count).to eq(0)
end
Spec Output:
$ rspec spec/models/committee_member_spec.rb
......#<CommitteeMember:0x00000007d1f888> {
:id => 1,
:committee_id => 1,
:member_id => 1,
:date_started => nil,
:date_ended => nil,
:created_at => Tue, 11 Aug 2015 19:22:51 UTC +00:00,
:updated_at => Tue, 11 Aug 2015 19:22:51 UTC +00:00
}
F
Failures:
1) CommitteeMember validations should fail with a string for date_ended
Failure/Error: expect(CommitteeMember.count).to eq(0)
expected: 0
got: 1
(compared using ==)
# ./spec/models/committee_member_spec.rb:52:in `block (3 levels) in <top (required)>'
Finished in 0.54864 seconds (files took 2.43 seconds to load)
7 examples, 1 failure
Failed examples:
rspec ./spec/models/committee_member_spec.rb:48 # CommitteeMember validations should fail with a string for date_ended
Since the attributes are date attributes, Rails automatically parses any values that you attempt to assign. If it cannot parse as a date, it will leave the value as nil, e.g. in the console:
c = CommitteeMember.new
c.date_started = 'S'
=> "S"
c.date_started
=> nil
In fact, Rails will actually parse a string into a Date:
c.date_started = '2016-1-1'
=> "2016-1-1"
c.date_started
=> Fri, 01 Jan 2016
c.date_started.class
=> Date
This means that you don't need to validate that your date fields are dates at all, because Rails won't store them otherwise. Instead, just validate that they exist:
validates_presence_of :date_started, :date_ended

Download image by using Grape and Carrierwave

I in my app/api/myapp/api.rb file I'm writing simple registration method:
params do
requires :email, type: String, regexp: /.+#.+/, allow_blank: false
requires :password, type: String, allow_blank: false
requires :name, type: String, allow_blank: false
requires :surname, type: String, allow_blank: false
requires :person, type: Integer, allow_blank: false
end
post :register do
User.create!(email: params[:email],
password: params[:password],
name: params[:name],
surname: params[:surname],
remote_avatar_url: Faker::Avatar.image)
end
As you can see, I'm using carrierwave gem to keep images of my model User. Now I'm just assigning random image from Faker gem.
How to receive image, that is sent from client and assign it to my new Model?
Just use the Rack::Multipart::UploadedFile as the example below.
desc 'Upload Image.'
params do
requires :file, :type => Rack::Multipart::UploadedFile
requires :id, :type => Integer
end
post ':id/avatar' do
File.open(params[:file].tempfile, 'r') do |f|
# Do whatever you need with this file.
# Here, you can store it in the server filesystem or in your database.
end
end

mongoid update_attributes changed?

I want to update_attributes and than check if information is changed
You can simply pass this code to rails console in existing rails + mongoid project
class TestModel
include Mongoid::Document
include Mongoid::Timestamps
field :name, type: String
end
test = TestModel.new({:name => "name 1"})
test.save()
=> true
test
=> created_at: 2012-11-14 13:48:26 UTC, updated_at: 2012-11-14 13:48:26 UTC
test.changed?
=> false
test.name_changed?
=> false
test.update_attributes({:name => "name 2"})
=> true
test.changed?
=> false
test.name_changed?
=> false
test
=> created_at: 2012-11-14 13:48:26 UTC, updated_at: 2012-11-14 13:49:23 UTC
Am I doing something wrong or this is a bug?
Its perfectly logic.
Dirty methods are meant to be used to check if an object has changed before it's saved. By definition a persisted object has no pending changes.
You should do:
test.assign_attributes(attributes)
test.changed? #=> true
test.save
See method definition.

Resources