My rails app is getting this error:
syntax error, unexpected ',', expecting =>
The line in my model that it is complaining about is this:
validates :body, presence: true,
length: {minimum: 2, maximum: 1000},
:chat_room_id, :user_id
Seems to be the comma between :chat_room_id and :user_id
Any ideas? Thanks!
you cannot write validation condition and after that, what to validate:
If presume you want something like this:
validates :body, presence: true, length: {minimum: 2, maximum: 1000}
validates :chat_room_id, :user_id, presence: true
Or another option:
validates :body, :chat_room_id, :user_id, presence: true
validates :body, length: {minimum: 2, maximum: 1000}
My parameter list:
{:utf8, :authenticity_token, :worklog => {:typee, :do, :todo, :feel, :plan_done, :plan, :week_feel, :score, :good, :nogood}, :commit}
after add thoes parameter get empty value in database
Related
I have an email ActiveRecord (sub-class, different PG DB) with the following validation:
class Email < DbRecord
belongs_to :user
attr_accessor :skip_validation
alias_method :skip_validation?, :skip_validation
validates :value,
presence: true,
uniqueness: true,
format: {
with: URI::MailTo::EMAIL_REGEXP,
message: "is an invalid email address",
allow_blank: true,
},
unless: :skip_validation?
before_validation { |record| record.value = record.value&.downcase }
skip_validation is nil. There are no other instance methods.
When there's no user_id the validation works as expected.
> e = Email.new(value: "foo#bar")
=> #<Email id: nil, user_id: nil, value: "foo#bar">
> e.valid?
=> false
When there's a user_id the bogus email doesn't trigger the validation.
> e = Email.new(user_id: 7, value: "foo#bar")
=> #<Email id: nil, user_id: 7, value: "foo#bar">
> e.valid?
=> true
Note that setting validate: true on belongs_to doesn't help:
class Email < DbRecord
belongs_to :user, validate: true
Still presents:
> e = Email.new(user_id: 7, value: "foo#bar")
=> #<Email id: nil, user_id: 7, value: "foo#bar">
> e.valid?
=> true
Why is that? What else should I be looking at/for?
Two-step answer:
"foo#bar" is a valid email according to URI::MailTo::EMAIL_REGEXP...
I can't even, but others have hit the same issue so...
As I always tell everyone else: check your assumptions. I assumed the validation was failing because of the email address, and in my sleep-deprived state I didn't verify the errors.
So why was it failing validation?
Rails 5 changed belongs_to to make the related ID mandatory, so in order for this to make sense (in my use-case) I also needed to add:
belongs_to :user, optional: true
to get the expected error messages back during 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).
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
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' }
This is stumping me; For some reason the db is saving the record with nil fields instead of my params. Can anyone help me understand why ActiveRecord isn't using my params?
db migration:
class CreateRoutes < ActiveRecord::Migration
def change
create_table :routes do |t|
t.integer :user_id
t.string :start_address
t.string :end_address
t.text :waypoints
t.text :schedule
t.integer :duration
t.timestamps
end
add_index :routes, :user_id
end
end
route.rb:
class Route < ActiveRecord::Base
attr_accessor :start_address, :end_address, :waypoints, :schedule, :duration
belongs_to :user
#serialize :waypoints, :schedule
validates :user_id, presence: true
validates :start_address, presence: true
validates :end_address, presence: true
validates :schedule, presence: true
validates :duration, presence: true, numericality: { only_integer: true, greater_than: 0 }
end
routes_controller.rb:
class RoutesController < ApplicationController
.
.
.
def create
logger.debug "\n\n*** #{params[:route]} ***"
#route = current_user.routes.build(params[:route])
logger.debug "*** The route is #{#route.inspect} ***\n\n"
if #route.save
flash[:success] = "Route saved!"
redirect_to user_path(current_user)
else
render 'new'
end
end
.
.
.
end
logger output:
*** {"start_address"=>"123 Sample St.", "end_address"=>"321 Elpmas St.", "waypoints"=>"None", "schedule"=>"Mondays", "duration"=>"15"} ***
*** The route is #<Route id: nil, user_id: 1, start_address: nil, end_address: nil, waypoints: nil, schedule: nil, duration: nil, created_at: nil, updated_at: nil> ***
The attr_accessors will overwrite the accessors generated by ActiveRecord, causing them to not be persisted in the DB--they'll be like plain old Ruby properties/members instead of the meta-programmed magic of ActiveRecord.
DB properties (persistent properties) can have things like attr_accessible, though.