This simple validation test is failing:
require 'test_helper'
class UserTest < ActiveSupport::TestCase
def setup
#user = User.new(name: "Example User",
email: "user#example.com",
character_attributes: {callsign: "example"},
password: "foobar",
password_confirmation: "foobar"
)
end
test "should be valid" do
assert #user.valid?, "#{#user.errors.messages}"
end
end
...with this message: character.sociable_id"=>["can't be blank"]
I don't understand why the user creation in UserTest is failing to make a valid User.
Each User has_one :character and each Character belongs_to a User.
The User model:
User.rb:
class User < ActiveRecord::Base
attr_accessor :remember_token, :activation_token, :reset_token
has_one :character, as: :sociable, dependent: :destroy
accepts_nested_attributes_for :character
has_secure_password
before_validation do
self.create_character unless character
end
before_save do
self.email.downcase!
end
before_create :create_activation_digest
validates :name, presence: true,
length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-]+(?:\.[a-z\d\-]+)*\.[a-z]+\z/i
validates :email, presence: true,
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates :password, length: { minimum: 6 }, allow_blank: true
validates :character, presence: true
.
.
end
The Character model:
Character.rb:
class Character < ActiveRecord::Base
belongs_to :sociable, polymorphic: true
has_many :posts, dependent: :destroy
before_save do
self.callsign.downcase!
end
validates :sociable_id, presence: true
VALID_CALLSIGN_REGEX = /\A[a-z\d\-.\_]+\z/i
validates :callsign, presence: true,
length: { maximum: 20 },
format: { with: VALID_CALLSIGN_REGEX },
uniqueness: { case_sensitive: false }
end
It should be:-
test "should be valid" do
assert #user.valid? , "#{#user.errors.messages}"
end
Related
I have a problem with my testing in rails with rspec. All in all I have a structure between 4 models, but for the moment I try to solve my testing for two of them. I'm using faker and FactoryGirl and have the following factories:
require 'faker'
FactoryGirl.define do
factory :user do |f|
f.name { Faker::Name}
f.email { Faker::Internet.email}
f.password {Faker::Internet.password}
f.role {"Kindergarten"}
end
end
require 'faker'
FactoryGirl.define do
factory :child do |f|
f.name { Faker::Name}
f.city { Faker::Address.city}
f.postalcode {Faker::Number.between(30000,35000)}
f.streed {Faker::Address.street_name}
f.add_number {Faker::Address.secondary_address}
f.disability { Faker::Boolean.boolean}
f.halal { Faker::Boolean.boolean}
f.koscha {Faker::Boolean.boolean}
f.vegetarian {Faker::Boolean.boolean}
f.vegan {Faker::Boolean.boolean}
f.allday { Faker::Boolean.boolean}
f.gender { Faker::Number.between(0,1)}
f.user_id {Faker::Number.between(1,10)}
end
end
and my controller test looks like that
require 'rails_helper'
require 'factory_girl_rails'
describe UsersController do
before do
3.times { FactoryGirl.create(:child)}
end
describe "GET #show" do
let(:user) { FactoryGirl.create(:user) }
before { get :show, id: user.id}
it "assigns the requested user to #user" do
assigns(:user).should eq user
end
it "renders the :show template"
end
describe "GET #new" do
let(:user) { FactoryGirl.create(:user) }
it "assigns a new User to #user" do
get :new, id: user.id
assigns(:user).should be_a_new(User)
end
it "renders the :new template"
end
end
When I try to run the test, I got this error message
UsersController GET #new assigns a new User to #user
Failure/Error: 3.times { FactoryGirl.create(:child)}
ActiveRecord::RecordInvalid:
Validation failed: User can't be blank
My relations and validations in the models are as follow
class Child < ApplicationRecord
has_many :relations, :dependent => :destroy
accepts_nested_attributes_for :relations
belongs_to :user
validates :user, presence: true
validates :name, presence: true, length: { maximum: 50 }
validates :city, presence: true, :on => :create
validates :postalcode, presence: true, numericality: true
validates :streed, presence: true
validates :add_number, presence: true
validates :disability, inclusion: { in: [true, false] }
validates :halal, inclusion: { in: [true, false] }
validates :koscha, inclusion: { in: [true, false] }
validates :vegetarian, inclusion: { in: [true, false] }
validates :vegan, inclusion: { in: [true, false] }
validates :allday, inclusion: { in: [true, false] }
validates :gender, presence: true
end
class User < ApplicationRecord
attr_accessor :remember_token, :activation_token, :reset_token
has_many :children, dependent: :destroy
has_many :kindergartens, dependent: :destroy
has_many :relations, dependent: :destroy
before_save :downcase_email
before_create :create_activation_digest
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates :role, presence: true
has_secure_password
validates :password, presence: true, length: { minimum: 6 }, allow_nil: true
end
My problem is, that I'm not sure if there is a fault in my rspec code or if I have made a mistake in my validations and relations in my normal models. Can someone help me?
I think that it would be better to post the whole factory for you. And I think you don't need to require faker if you have it in Gemfile.
FactoryGirl.define do
factory :child do
name { Faker::Name}
city { Faker::Address.city}
postalcode {Faker::Number.between(30000,35000)}
streed {Faker::Address.street_name}
add_number {Faker::Address.secondary_address}
disability { Faker::Boolean.boolean}
halal { Faker::Boolean.boolean}
koscha {Faker::Boolean.boolean}
vegetarian {Faker::Boolean.boolean}
vegan {Faker::Boolean.boolean}
allday { Faker::Boolean.boolean}
gender { Faker::Number.between(0,1)}
user
end
end
Inside specs when you need to create a child for the particular user:
let(:current_user) { create :user }
let(:child) { create :child, user: current_user }
Try to change your controller spec:
describe UsersController do
let(:user) { create(:user) }
describe "GET #show" do
before { get :show, params: { id: user.id } }
it "assigns the requested user to #user" do
assigns(:user).should eq user
end
it "renders the :show template"
it { expect(response).to have_http_status 200 }
end
describe "GET #new" do
before { get :new }
it "assigns a new User to #user" do
assigns(:user).should be_a_new(User)
end
it "renders the :new template"
end
end
Have many to many relationship but keep getting the same error: ActiveModel::UnknownAttributeError: unknown attribute 'employee_id' for EmployeeSkill. I've checked both my models and it seems like i have IDs for both so not sure what to do?
class Skill < ApplicationRecord
validates :skill_name, presence: true, length: { minimum: 3, maximum: 30}
validates_uniqueness_of :skill_name
has_many :employee_skills
has_many :employees, through: :employee_skills
end
...
class Employee < ApplicationRecord
before_save { self.email = email.downcase }
#validates :email, presence: true, length: { maximum: 30 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_many :employee_skills
has_many :skills, through: :employee_skills
end
...
class EmployeeSkill < ApplicationRecord
belongs_to :employee
belongs_to :skill
end
1) Check if in your migration files and database the corresponding id's are in place.
2) Restart the server (weird but sometimes is needed).
Your code looks good so I think is one of two cases I mention.
Regards,
I am implementing something of a todo list with a user model and a List model with a date attribute.
On the user show page, I retrieve today's to do list.
How do I go about querying a user todo list for the previous and/or the next day.
All insights are welcome, thanks!
class User < ActiveRecord::Base
before_save { self.email = email.downcase }
before_save { self.username = username.downcase }
has_many :to_do_lists, dependent: :destroy
has_many :tasks, dependent: :destroy
validates_presence_of :first_name, :last_name
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-]+(?:\.[a-z\d\-]+)*\.[a-z]+\z/i
VALID_USERNAME_REGEX = /\A[a-z_0-9]+\z/i
validates :email, presence: true,
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates :username, presence: true,
format: { with: VALID_USERNAME_REGEX },
uniqueness: { case_sensitive: false }
def name
[first_name, last_name].compact.join(' ')
end
end
and the list model
class ToDoList < ActiveRecord::Base
belongs_to :user
has_many :tasks, dependent: :destroy
validates_presence_of :user_id
validates :date, presence: true,
uniqueness: {scope: :user_id}
end
Rails adds many helpful methods to Time to make this type of query quite intuitive. Since you validate that a user has only one to do list for each day:
#next_day_list = #user.to_do_lists.find_by_date(Date.today.tomorrow)
#prev_day_list = #user.to_do_lists.find_by_date(Date.today.yesterday)
In our app's User model, we already have:
attr_accessor :remember_token, :activation_token, :reset_token
before_save :downcase_email
before_create :create_activation_digest
before_save { self.email = email.downcase }
validates :first_name, presence: true, length: { maximum: 50 }
validates :last_name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
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
Now, we need to add relationship associations to the model, namely:
has_many :roles, dependent: :destroy
has_many :agendas, through: :roles
Does it matter whether we include the latter go BEFORE or AFTER the former, in the model?
If so, what is the recommended / preferred / best way?
It doesn't matter, but the important thing is to be consistent. A usual best practice is to first do all you can to declare the class' structure, before you get in to any operational details. For example:
class User < ActiveRecord::Base
attr_accessor :remember_token, :activation_token, :reset_token
has_many :roles, dependent: :destroy
has_many :agendas, through: :roles
before_save :downcase_email
before_create :create_activation_digest
before_save { self.email = email.downcase }
validates :first_name, presence: true, length: { maximum: 50 }
validates :last_name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/
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
end
Again, this is just one way to do things, but it's very common amongst Rails applications.
I'm working through an API for Rails and have been fumbling how to set up the associations, the spec, and the controller for my Get route. The goal - As a user I want to get all the notes closest to my location that have not been viewed. I know the viewed? logic is off, as is the Query Interface in the Recipients Model and Nearests Controller.
Here's the Error Rspec is giving me:
Failure/Error: note1 = create(:note)
NoMethodError:
undefined method `recipient_id=' for #<Note:0x007fd2a40e1400>
Here's the spec:
describe 'GET /v1/notes/nearests?lat=&lon=&radius=' do
it 'returns the notes within the given radius' do
near_note1 = create(:note, lat: 37.760322, lon: -122.429667)
near_note2 = create(:note, lat: 37.760322, lon: -122.429667)
lat = 37.771098
lon = -122.430782
radius = 10
get "/v1/notes/nearests?lat=#{lat}&lon=#{lon}&radius=#{radius}"
expect(response_json).to eq([
{
'id' => [near_note1.id, near.note2.id],
# 'lat' => near_note1.lat,
# 'lon' => near_note1.lon,
'note_text' => [near_note1.note_text, near_note2.note_text],
'photo_uri' => [near_note1.photo_uri, near_note2.photo.uri],
# 'expiration' => near_note.expiration.as_json,
'viewed' => [near_note1.viewed?, near_note2.viewed?]
},
])
end
end
Here is the controller code:
def index
#notes = Note.near([
params[:recipient_id],
params[:lat],
params[:lon]],
radius: :APP_CONFIG['radius'],
units: :APP_CONFIG['units']
)
end
Here are the Factories - Notes
FactoryGirl.define do
factory :note do |u|
sender_id {FactoryGirl.create(:user).id}
recipient_id {FactoryGirl.create(:user).id}
lat 1.5
lon 1.5
note_text "MyString"
photo_uri "MyString"
expiration Time.zone.now.utc
end
end
My Models:
User Model
class User < ActiveRecord::Base
has_many :notes
validates :first_name, :last_name, :pw, presence: true
validates :email, :username, :devicetoken, presence: true, uniqueness: true
validates :email, length: { minimum: 8 }
end
Note Model
class Note < ActiveRecord::Base
belongs_to :user, foreign_key: 'sender_id', class_name: 'User'
has_many :recipients, foreign_key: 'recipient_id', class_name: 'User'
validates :sender_id, presence: true
validates :lat, presence: true
validates :lon, presence: true
validates :note_text, presence:true
validates :expiration, presence: true
reverse_geocoded_by :lat, :lon
end
Recipients Model
class Recipient < ActiveRecord::Base
belongs_to :note, foreign_key: 'recipient_id', class_name: 'Note'
def get_recipient
Note.find(:all, params[:note_id])
end
def viewed?
end
end