Cannot create new Activerecord with belongs_to relationship - ruby-on-rails

I am a beginner with Ruby on Rails and I am trying to create a seed.rb file to populate my database.
However I am having problems creating a new Request record.
This is my seed file:
if Rails.env == "development" || Rails.env == "test"
avaya = Company.create!(name: "Avaya")
microsoft = Company.create!(name: "Microsoft")
bradesco = Company.create!(name: "Bradesco")
customer = Customer.create!(name: "Leon Schmidt", email: "leon.schmidt#avaya.com", company_id: avaya.id)
Customer.create!(name: "Teri Wright", email: "teri.wright#avaya.com", company_id: avaya.id)
Customer.create!(name: "Jasmine Bush", email: "jasmine.bush#microsoft.com", company_id: microsoft.id)
Customer.create!(name: "Jake Blair", email: "jake.blair#bradesco.com.br", company_id: bradesco.id)
rate = Rate.create!(rate: 0.0165, days: 10, default_rate: true)
Request.create!(title_value: 1500, term: 28, monthly_revenue: 75000, receivable_value: 1425.75, rate_id: rate.id, customer_id: customer.id)
elsif Rails.env == "production"
Rate.create(rate: 0.0165, days: 10, default_rate: true)
end
Whenever I run rake db:reset to repopulate the development database I get this error:
rake aborted!
ActiveRecord::RecordInvalid: Validation failed: Customers must exist
c:/Desenvolvimento/Coding Tests/FactoringRateCalculator/db/seeds.rb:23:in `<top (required)>'
Tasks: TOP => db:reset => db:setup => db:seed
Please note that the line 23 is: Request.create!(title_value: 1500, term: 28, monthly_revenue: 75000, receivable_value: 1425.75, rate_id: rate.id, customer_id: customer.id)
My models are below:
class Customer < ApplicationRecord
belongs_to :company
has_many :requests
validates_associated :requests
validates :name, presence: true
validates :email, presence: true, email: true
end
class Request < ApplicationRecord
belongs_to :customers, required: true
belongs_to :rate, required: true
validates :term, presence: true, numericality: { greater_than_or_equal_to: 10 }
validates :title_value, presence: true, numericality: { greater_than_or_equal_to: 500 }
validates :monthly_revenue, :receivable_value, presence: true, numericality: true
end
class Rate < ApplicationRecord
has_many :requests
validates_associated :requests
validates :rate, numericality: true, presence: true
validates :days, numericality: { greater_than_or_equal_to: 10 }, presence: true
validates :rate, :days, :default_rate, presence: true
end
class Company < ApplicationRecord
has_many :customers
validates_associated :customers
validates :name, presence: true
end
I am using Ruby 2.3 and Rails 5.1.

Your required validation is specified with the plural version of your model:
belongs_to :customers, required: true
Try using the singular way:
belongs_to :customer, required: true
That's why the error says "Customers": "ActiveRecord::RecordInvalid: Validation failed: Customers must exist", because your seeds have been made following the relationship you specify.

Related

Unit testing a polymorphic association with fixtures in rails 4

I need to unit test a promotions model where every campaign has a URL. There is a polymorphic association between promotions and reference_link. the reference link fixture:
reference_link:
linkable:
fix_1 (PromoCode)
How do I convince rails that the promotions fixture does indeed have a URL belonging to it?
In promotions test helper:
test "should have a URL associated with the promo code" do
promo_code = promo_codes(:fix_1)
promo_code.reference_link.url = nil
assert_not promo_code.valid?
promo_code2 = promo_codes(:fix_2)
assert promo_code2.valid?
end
promocode.rb
class PromoCode < ActiveRecord::Base
belongs_to :reward
has_one :reference_link, as: :linkable, dependent: :destroy
validates :email, presence: true
validates :code, presence: true
end
reference_link.rb
class ReferenceLink < ActiveRecord::Base
belongs_to :linkable, polymorphic: true,touch: true
validates :link_name, presence: true
validates :link_url, presence: true
validates_format_of :link_url, :with => /\A#{URI::regexp(['http', 'https'])}\z/
validates_length_of :link_url,:link_name, :maximum => 255
end
It's simple, you almost got it right. First, ensure the fixtures are correctly set:
# promo_codes.yml
promo_1:
email: 'foobar#gmail.com'
name: 'Foobar'
# reference_links.yml
reference_1:
linkable: promo_1
link_name: 'lorem'
link_url: 'http://loremipsum.com'
The tests:
# promotion_test.rb
test "should have a URL associated with the promo code" do
promo_code = promo_codes(:promo_1)
assert_eq true, promo_code.reference_link.present?
end
Do not forget that file naming is an important part of convention that Rails use.

FactoryGirl giving me an error

I got this model:
rails g model Absence user:references company:references from:date to:date date:date category:integer hours:decimal remarks
This also generates:
FactoryGirl.define do
factory :absence do
user nil
company nil
from nil
to nil
date nil
category 0
hours "8.00"
remarks "MyString"
end
end
I set from, to and date to nil because it's either: from and to OR a certain date.
When I try this in my spec:
#absence = create(:absence, user: #company.owner, from: "2015-09-10", to: "2015-09-10", hours: 4)
I receive this error message:
NoMethodError:
undefined method `from=' for #<Absence:0x007f81f5494b88>
What could be wrong?
Edit:
When I remove the
from nil
from the factories/absences.rb I'm getting it on the next field (to) and after removing that I'm seeing the error message on category.
Edit2:
Model:
class Absence < ActiveRecord::Base
belongs_to :user
belongs_to :company
enum type: {holiday: 0, sick: 1}
validates :from, presence: true, if: '!user_id.nil?'
validates :to, presence: true, if: '!user_id.nil?'
validates :date, presence: true, if: '!company_id.nil?'
validates :hours, presence: true, if: '!user_id.nil?'
validates :hours, :numericality => { :greater_than_or_equal_to => 0 }, if: '!user_id.nil?'
validates :category, presence: true, if: '!user_id.nil?'
validates_numericality_of :company_id, allow_nil: true
validates_numericality_of :user_id, allow_nil: true
validate :company_xor_user
validate :to_date_after_from_date
validate :hours_smaller_than_workday
validate :non_overlapping
after_save :calculate_time_checks
after_destroy :calculate_time_checks_delete
DB:
https://www.evernote.com/shard/s29/sh/e8c1429d-9fa7-475b-87e8-3dc11a3f3978/08a7e7d6dfd80c6f407339cab97734c2
FINALLY found the real cause.
At first I had the Absence model created with an attribute named 'type'. This was migrated to both the development and test database. Afterwards I changed it to category and added 'from' and 'to' as well and did a rollback and migrated again (but not on test!).
By using pry
require 'pry'; binding.pry
in the test I did Absence.columns and noticed the difference.

Custom validation causing other validations to fail

Title pretty much explains the problem.
Here were my validations for my model:
class Lesson < ActiveRecord::Base
belongs_to :school
has_many :users, through: :goals
has_many :goals, dependent: :destroy
validates :school_id, presence: true
validates :date, presence: true, uniqueness: { scope: :school_id }
validates :attendance, numericality: { only_integer: true,
greater_than: 0 },
presence: true, if: :finished?
validates :lesson_plan_week_number, numericality: { only_integer: true,
greater_than: 0 },
presence: true, if: :finished?
end
All of my model tests (aside from the ones dealing with the custom validation) pass with the above code
Then I added validate :motion_presence and the following private method:
def motion_validation
if debate?
errors.add(:motion, "must be present if a debate was held")
else
errors.add(:motion, "cannot be present if a debate was held")
end
end
and now the tests that once passed are failing. What's happening?
Here's the relevant code in the model if I'm organizing it incorrectly
class Lesson < ActiveRecord::Base
belongs_to :school
has_many :users, through: :goals
has_many :goals, dependent: :destroy
validates :school_id, presence: true
validates :date, presence: true, uniqueness: { scope: :school_id }
validates :attendance, numericality: { only_integer: true,
greater_than: 0 },
presence: true, if: :finished?
validates :lesson_plan_week_number, numericality: { only_integer: true,
greater_than: 0 },
presence: true, if: :finished?
validate :motion_presence
private
# Validates the motion depending on debate?
def motion_presence
if debate?
errors.add(:motion, "must be present if a debate was held")
else
errors.add(:motion, "cannot be present if a debate was held")
end
end
end
def motion_presence
if debate?
errors.add(:motion, "must be present if a debate was held")
else
errors.add(:motion, "cannot be present if a debate was held")
end
end
This will always fail because you added to errors in either case.
If you wanted to fail it for multiple conditions, then try doing it in elsif. else means EVERYTHING ELSE and its failing always.
Do it like this:
def motion_presence
if debate?
errors.add(:motion, "must be present if a debate was held")
elsif some_condition
errors.add(:motion, "cannot be present if a debate was held")
end
end
That is because in any case whether debate? returns true or false, it is adding errors to the motion so it will never be successful which results in not saving the lesson object as errors are already added for motion field.
I think you need to add a case where it should just return without adding any errors. Besides just add errors for specific cases

Rails NoMethodError: undefined method `valid?'

I am relatively new to rails and I can't figure out how to fix this bug.
So here are my models:
User
class User < ActiveRecord::Base
before_save { email.downcase! }
has_many :tickets
has_many :events, through: :tickets
validates :first_name, presence: true
validates :last_name, presence: true
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255},
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
end
Event:
class Event < ActiveRecord::Base
has_many :tickets
has_many :users, through: :tickets
validates :event_title, presence: true
validates :event_place, presence: true
validates :event_description, presence: true
validates :event_date, presence: true
validates_numericality_of :event_number_tickets, presence: true, numericality: { only_integer: true }, greater_than: 0
end
Ticket:
class Ticket < ActiveRecord::Base
belongs_to :user
belongs_to :event
end
I have a test file for tickets which is
require 'test_helper'
class TicketTest < ActiveSupport::TestCase
def setup
#user = User.new(first_name: "Example", last_name: "User")
#event = Event.new(event_title: "Example Event",
event_place: "123 Example Ave.",
event_description: "Our example event for children to get introduced to technology",
event_date: DateTime.now,
event_number_tickets: 30)
#ticket = Ticket.new(event: #event, ticket_type: "regular", number_of_children: 1)
#user.tickets << #ticket
end
test "should be valid" do
assert #user.tickets.valid?
end
end
Whenever I run this test I get the following error:
NoMethodError: undefined method `valid?' for #<Ticket::ActiveRecord_Associations_CollectionProxy:0x007fae767617c8>
test/models/ticket_test.rb:18:in `block in <class:TicketTest>'
Do I have to create a custom valid method for this particular example.
There's not a valid? method for an ActiveRecord collection. If you're trying to test that the last Ticket you created is valid, you can do something like assert #ticket.valid?.
I think you might be doing a bit too much work in your setup method. You could try to just setup your User and Event model in the setup, and break the rest of what you described into different test blocks.

Elasticsearch, Tire & Associations

Running: Ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-darwin11.2.0], Rails 3.2.0
I'm trying to get elastic search working through the TIRE gem across associations. For some reason I keep getting the following error/errors when performing a rake on a TIRE import or occasionally on a view:
Daves-MacBook-Pro:outdoor dave$ rake environment tire:import CLASS=Gear FORCE=true
[IMPORT] Deleting index 'gears'
[IMPORT] Creating index 'gears' with mapping:
{"gear":{"properties":{}}}
[IMPORT] Starting import for the 'Gear' class
--------------------------------------------------------------------------------
101/101 | 100% rake aborted!######################################
undefined method `last_name' for nil:NilClass
Tasks: TOP => tire:import
Here are my models:
GEAR
class Gear < ActiveRecord::Base
attr_accessible :title, :size, :price, :image_url, :sub_category_id, :user_id
belongs_to :user
belongs_to :sub_category
validates :title, presence: true
validates :size, presence: true
validates :price, presence: true
validates :sub_category_id, presence: true
validates :user_id, presence: true
include Tire::Model::Search
include Tire::Model::Callbacks
def self.search(params)
tire.search(load: true, page: params[:page], per_page: 18) do
query { string params[:query]} if params[:query].present?
end
end
def to_indexed_json
to_json(methods: [:sub_category_name, :user_last_name, :user_first_name, :user_email])
end
def sub_category_name
sub_category.name
end
def user_first_name
user.first_name
end
def user_last_name
user.last_name
end
def user_email
user.email
end
end
USER
class User < ActiveRecord::Base
attr_accessible :first_name, :last_name, :email, :password, :password_confirmation
has_secure_password
has_many :gears
before_save :create_remember_token
email_regex = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :first_name, presence: true,
length: {:maximum => 50 }
validates :last_name, presence: true,
length: {:maximum => 50 }
validates :email, presence: true,
format: {:with => email_regex},
uniqueness: {:case_sensitive => false}
validates :password, presence: true,
confirmation: true,
length: {within: 6..40}
def name
first_name + " " + last_name
end
private
def create_remember_token
self.remember_token = SecureRandom.urlsafe_base64
end
end
Sub_Category
class SubCategory < ActiveRecord::Base
attr_accessible :name
belongs_to :category
has_many :gears
end
What am I missing? Thanks.
I had a few NIL values in my database that was the reason for the errors. Hopefully this can save a few people some time.

Resources