In the following example, is there a way to retrieve the name of the parameter being currently validated inside the if proc ?
class MyModel < ActiveRecord::Base
with_options if: proc{|o| "how to retreive the parameter being validated here?"} do
validates :param_1, presence: true
validates :param_2, presence: true
end
end
I would like to avoid this kind of solution:
class MyModel < ActiveRecord::Base
validates :param_1, presence: true, if: proc{|o| o.need_validation?(:param_1)}
validates :param_2, presence: true, if: proc{|o| o.need_validation?(:param_2)}
end
If you wish to know name, and other data like option to validation, use validators:
app/validators/param_validator.rb:
ParamValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
# your validation code here...
end
end
The arguments say about themself.
Use it in a model:
validates :param_1, param: true
validates :param_2, param: true
If each of the validations are identical apart from the name, you could iterate over them:
class MyModel < ActiveRecord::Base
[:param1,:param2].each do |param|
validates param, presence: true, if: proc{|o| o.need_validation?(param) }
end
end
I'm pretty sure there is no easy answer to my question, I'll find an other way.
Related
assuming i have two models human and male, they both have similar attributes but not all the attributes, for example:
class Human < ApplicationRecord
has_many :males
validates :name, presence: true
validates :age, presence: true
validates :date_of_birth, presence: true
validates :identity, presence: true
end
class Male < ApplicationRecord
belongs_to :human
validates :name, presence: true
validates :age, presence: true
end
now what i want to do is when i use human.males.build i want the new male instance to inherit the shared attributes like name and age
instead of using this behavior human.males.build({attributes})
I'm thinking of overwriting the initialize (alias of build) method of Male model which will do the trick:
def initialize(attributes = {}, &block)
super(attributes, &block)
self.name = human.name unless attributes[:name].present?
self.age = human.age unless attributes[:age].present?
end
But honestly, I don't think this is a safe and generic way for the problem.
I have a mode named Exam.
There are some columns in exames:
:title
:subject_id
:exam_type
I want to know how to implement this:
class Exam < ApplicationRecord
validates :title, presence: true
validates :subject_id, presence: true, if: :no_exam_type?
def no_exam_type?
self.exam_type == ""
end
end
That is to say, I want to create a exam:
Exam.create(title: "first exam", exam_type: "something")
The subject_id must be exist, when exam_type is blank, such as exam_type="" or just do:
Exam.create(title: "first exam", subject_id: 3)
because exam_type has a default blank value.
But the subject_id doesn't necessary provide, when exam_type not blank, such as exam_type="something".
Exam.create(title: "first exam", exam_type: "something", subject_id: 3)
I test it, but no lucky.
How to do that? Thanks appreciate.
In Rails 5 belongs_to associations default to optional: false. Which means that the model will automatically validate the presence of the association.
class Thing < ApplicationRecord
belongs_to :other_thing
end
Thing.create!
# => ActiveRecord::RecordInvalid: Validation failed: other_thing can't be blank
So you need to set the association as optional and make sure the column is nullable.
class Exam < ApplicationRecord
belongs_to :subject, optional: true
validates :title, presence: true
validates :subject_id, presence: true, if: :no_exam_type?
def no_exam_type?
!self.exam_type.present?
end
end
Have you tried like this.
validates :subject_id, presence: true, :if => exam_type.blank?
you can refer the doc here to suite your requirement
use validates_presence_of instead.
validates_presence_of :subject_id, if: :no_exam_type?
def no_exam_type?
self.exam_type.nil?
end
I'm trying to query only objects from the database whose boolean attribute "in_season" returns true and its not working.
class Item < ApplicationRecord
validates :name, presence: true, uniqueness: true
validates :price, presence: true, numericality: true
validates :quantity, presence: true, numericality: { only_integer: true }
validates :description, presence: true
def self.in_season
where("in_season = ?", "true")
end
end
class ItemsController < ApplicationController
def index
#items = Item.in_season
end
end
I feel like everything is set up correctly and I'm not getting any errors, but my index page is blank because none of the items are being queried correctly.
You need to fix the syntax. Your mistake is that you're passing a string "true", whereas you want to pass boolean value true.
def self.in_season
where(in_season: true)
end
It's more Railsy to use scope for such needs:
scope :in_season, -> { where(in_season: true) }
Read more about scoping in Rails Guides on scopes.
I'm having an issue with my rails application. Basically I'm trying to make a simple website where people can apply for jobs. When the user clicks "show" on the jobs page (the page consists of a table of job offers)to show a particular job offer they are brought to a new page where more information is given on the job, and a text box where the person can write a message to make a request for the job.(I plan to make this a more efficient method such as a link to the candidates page but for the moment I'm keeping it as a simple text box where the candidate can comment). The problem arises when the candidate tries to submit the comment, I get the error mentioned above. Could it be an issue in the models as there is a number of relationships set up, i.e. a job has many requests, requests has many candidates etc, etc. I've gotten this message before and it was simply a case of fixing a variable name mistake, however I've been looking over this for a while, had it proof read by a friend and I still can't find the error.I would greatly appreciate any help!
RequestsController
class RequestsController < ApplicationController
before_action :authorise
#set_request, only: [:show, :edit, :update, :destroy]
def create
#job = Job.find params[:job_id]
#request = #job.requests.new(request_params) <- Error highlights this line
#request.candidate_id = #current_candidate.id #sets the user_id FK
#request.save #saves the #comment
# object to the comments table
respond_to do |format|
format.html{redirect_to #job}
end
end
private
def comment_params
#This is the method ehich whitelists the data fields from the format
params.require(:request).permit(:content, :job_id, :candidate_id)
end
end
Request Model
class Request < ActiveRecord::Base
belongs_to :job, dependent: :destroy
has_many :candidates
end
Candidate Model
class Candidate < ActiveRecord::Base
has_secure_password
validates_uniqueness_of:can_email
belongs_to :request
validates :can_name, presence: true
validates :can_surname, presence: true
validates :college, presence: true
validates :can_email, presence: true
validates :address, presence: true
validates :experience, presence: true
validates :password_digest, presence: true
validates :college_year, numericality: { only_integer: true }
end
Job Model
class Job < ActiveRecord::Base
belongs_to :sector
has_many :requests, dependent: :destroy
validates :name, presence: true
validates :employer, presence: true
validates :sector, presence: true
validates :experience_req, presence: true
validates :job_info, presence: true
end
def comment_params
should be
def request_params
I have the following in my models/user.rb:
validates :company, presence: true
validates :title, presence: true
I have a secondary view where I want to create a user but not require this user to enter a company and a title. How would I do that without modifying the main user.rb?
This is for Rails 3.2
You can do by declaring custom validations the way #BroiSatse has answered or when saving the user you can pass validate: false as argument, do this way
#user.save(:validate => false)
I usually do sth like:
class User < AR::Base
validates :company, :title, presence: true, if: :validate_company_and_title?
def validate_company_and_title?
#validate_company_and_title.nil? || #validate_company_and_title
end
def skip_company_and_title_validation!
#validate_company_and_title = false
end
end
Then in your controller create action for given view you can do:
#user.skip_company_and_title_validation!