I am facing strange issue in validating presence of association in a derived class.
Class Contact < ActiveRecord::Base
has_and_belongs_to_many :things
end
Class SubContact < Contact
# validates_presence_of :things
validate :must_have_things
def must_have_things
if things.blank?
errors.add("Must select things")
end
end
end
In SubContact class, I am trying to validate presence of things but nothing is working. I have tried both custom and built in validators
How can I achieve this?
add needs an attribute. Try using:
errors.add(:base, "Must not be blank")
In this case, it is the base class but it can be any other attribute too. Mention an attribute name of the SubContract class or :base.
Related
I'm trying to make a form to create new record for a model user which has one billing_information. Billing_information has an attribute account_name that I want to include in the form. I tried using the delegate method but it's not working. It produces :-
error: unknown attribute 'billing_information_account_name' for User.
class User < ActiveRecord::Base
accepts_nested_attributes_for :billing_information
has_one :billing_information, inverse_of: :user
delegate :account_name, to: :billing_information, allow_nil: true
rails_admin do
create do
field :name
field :email
field :billing_information_account_name do
def value
bindings[:object].account_name
end
end
end
end
end
Does anyone has a better solution? Thank you.
Sadly, you won't get help from rails admin in this case, but it can be done.
You have to add a new virtual field and handle in a setter the input. Take a look at this example.
class User < ApplicationRecord
has_one :billing_information, inverse_of: :user
# A getter used to populate the field value on rails admin
def billing_information_account_name
billing_information.account_name
end
# A setter that will be called with whatever the user wrote in your field
def billing_information_account_name=(name)
billing_information.update(account_name: name)
end
rails_admin do
configure :billing_information_account_name, :text do
virtual?
end
edit do
field :billing_information_account_name
end
end
end
You can always create the full billing_information using the nested attributes strategy, meaning add the billing_information field and you'll get a nice form to fill all the information.
My models are
class Company
has_many :admins
validate :has_one_admin_validation
private
def has_one_admin_validation
errors.add(:admins, :not_enough) if admins.size < 1
end
end
class Admin
belong_to :company
end
Now, suppose I have a controller that can remove admins. How do I prevent removing the admin (ie generate errors) if it is the only admin of its company ?
If I understand well, I have to remove the admin from the memory object, and try to "save/destroy" if by validating the company first ?
I don't think you need a custom validation at all on the Company model. You can use the 'length' validation on your association.
validates :admins, length: { minimum: 1 }
If that doesn't work, you should also be able to check the 'marked_for_destruction?' property. You should also be able to validate the reciprocal relationship with a 'presence: true' validation.
class Company
has_many :admins
validate :has_one_admin_validation
private
def has_one_admin_validation
errors.add :admins, "You need at least one admin" if admins.reject(&:marked_for_destruction?).empty?
end
end
class Admin
belongs_to :company, presence: true
end
You may also want to look at using the before_destroy callback in your Admin class.
before_destroy :has_company_with_no_other_admins
...
private
def has_company_with_no_other_admins
return false if company.admins.length < 2
true
end
There's a pretty good description of using before_destroy here: https://stackoverflow.com/a/123190/6441528
That's worth looking at because implementations vary based on your Rails version.
I made the following class, but it didn't work correctly.
class User < ActiveRecord::Base
validate :validate_department_code, on: :create
def validate_department_code
if self.department_code.present?
department = Department_code.find_by_name(self.department_code)
user.build_participation(department: department)
else
self.errors.add(:department_code, :not_found)
end
end
end
After validation, the user is saved in DB, but the participation is not saved. So user.participation becomes nil.
How can I solve the problem?
In User.rb, add an after_create on a condition.
It should look like:
after_create :create_participation, if: :department_code.present?
I have a many to many relationship with DoctorProfile and Insurance. I'd like to create these associations off of a form from a client side app. I'm sending back an array of doctor_insurances_ids and trying to create the association in one line. Is it possible to send back an array of doctor_insurances ids? If so what's the proper way to name it for mass assignment in the params?
The error I'm getting with the following code is
ActiveRecord::UnknownAttributeError: unknown attribute 'doctor_insurances_ids' for DoctorProfile.
class DoctorProfile
has_many :doctor_insurances
accepts_nested_attributes_for :doctor_insurances # not sure if needed
class Insurance < ActiveRecord::Base
has_many :doctor_insurances
class DoctorInsurance < ActiveRecord::Base
# only fields are `doctor_profile_id` and `insurance_id`
belongs_to :doctor_profile
belongs_to :insurance
def create
params = {"first_name"=>"steve",
"last_name"=>"johanson",
"email"=>"steve#ymail.com",
"password_digest"=>"password",
"specialty_id"=>262,
"doctor_insurances_ids"=>["44", "47"]}
DoctorProfile.create(params)
end
You're not putting a doctor_insurance_id in your Doctor Profile so your DoctorProfile.create(params) line isn't going to work. You could do something like this:
def create
doctor = DoctorProfile.create(doctor_profile_params)
params["doctor_insurances_ids"].each do |x|
DoctorInsurance.create(doctor_profile_id: doctor.id, insurance_id: x)
end
end
def doctor_profile_params
params.require(:doctor_profile).permit(:first_name, :last_name, :email, :password_digest, :specialty_id)
end
I want to create user-specific validations.
User has a column called "rule_values" which is a serialized hash of certain quantities.
In a separate model, Foo, I have a validation:
class Foo < ActiveRecord::Base
belongs_to :user
n = self.user.rule_values[:max_awesome_rating] #this line is giving me trouble!
validates_presence_of :awesome_rating, :in => 1..n
end
It seems that self refers to Foo (which is why I'm getting an undefined method error) and not an instance of Foo. How can I access the User instance from within the Foo model?
How about creating a custom validation on Foo something like this?
class Foo < ActiveRecord::Base
validate do |foo|
n = foo.user.rule_values[:max_awesome_rating]
unless (1..n).include? foo.awesome_rating
foo.errors.add :awesome_rating, "must be present and be between 1 and #{n}"
end
end
end
This way you have access to the instance and the user association
Rails supports custom validations (using validate). Here's an idea of how it might work (did not check it though):
class Foo < ActiveRecord::Base
belongs_to :user
validate :awesome_rating_is_in_range
def awesome_rating_is_in_range
errors.add(:awesome_rating, 'not in range') unless (1..user.rule_values[:max_awesome_rating]).include? awesome_rating
end
end