I've got app with model where prescriptions are connected with medicines via relations table.
I use one form to create one prescription with 5 relations which contains information about medicine_id, amount, daily and so on. However, medicine table has got a lot more information and thats what I would like to use when validating.
For example - I want to check if field dose from table medicines is like `'%pills'. If so, I would like to do some calculation to check if an amount that user put during filling the form is in range (lets say 30-40 is only correct for this specific medicine)
My relation model:
class Relation < ActiveRecord::Base
belongs_to :prescription
belongs_to :medicine
validates :amount, numericality: {only_integer: true, :greater_than_or_equal_to => 1 }
validates :daily, numericality: {only_integer: true, :greater_than_or_equal_to => 1 }
validates :period_in_days, numericality: {only_integer: true, :greater_than_or_equal_to => 1 }
validate :amount_limit, :if => :pills_form?
private
def amount_limit
end
def pills_form
end
end
How can I get these informations that are in the medicine table when Im validating relations? Or is there any other, more proper way of doing this?
Aswer thanks to the #BroiSatse
class Relation < ActiveRecord::Base
belongs_to :prescription
belongs_to :medicine
validates :amount, numericality: {only_integer: true, :greater_than_or_equal_to => 1 }
validates :daily, numericality: {only_integer: true, :greater_than_or_equal_to => 1 }
validate :amount_limit, :if => :pills_form?
private
def amount_limit
max_amount = self.daily * 90
in_box_amount = medicine.cardinality.scan(/\d+/).first
sum = self.amount * in_box_amount.to_i
if sum > max_amount
errors.add(:amount, "An amount of medicine cannot exceed 90 days of treatment.")
end
end
def pills_form?
pill_form_array = ['plaster' , 'globul', 'czop', 'guma', 'tablet', 'pastyl', 'kaps', 'lamel']
pill_form_array.any? { |item| medicine.form =~ /#{item}/ }
end
end
Related
I'm looking to create a "related posts" section, but cheating a little by just displaying the next 6 posts in the series on my show.html.erb
How would I go about showing these?
Thanks,
Jon
EDIT - ADDED POST MODEL
class Post < ActiveRecord::Base
has_and_belongs_to_many :categories
belongs_to :user
is_impressionable :counter_cache => true, :column_name => :view_count
acts_as_taggable_on :tags
extend FriendlyId
friendly_id :title, use: :slugged
scope :featured, -> { where(:featured => true) }
scope :recent, -> { order(created_at: :desc) }
scope :hot, -> { order(view_count: :desc) }
scope :longest, -> { order(duration: :desc) }
def self.sort_by(sort_param)
case sort_param
when 'recent'
recent
when 'hot'
hot
when 'longest'
longest
else
recent
end
end
end
You didn't post the code for your Post model, but assuming it has a posted_at attribute and #post is currently displayed, you can do:
Post.where.not(id: #post.id).order('posted_at desc').limit(6)
I have a model 'place_detail' that has many a child 'emails'
has_many :emails, :dependent => :destroy
and in the email model:
belongs_to :place_detail
Now in the place_detail i want to make sur i added a email to check a attribut 'has_email'
so i added:
before_save :check_if_has_email
...
def check_if_has_email
if emails.count >0
self.has_email = true;
else
self.has_email = false;
end
end
the problem is that the attribute has_email does not check event if i created a email child. what i understand is that the parent is saved before the child
how can i get my has_email checked in place_detail when i create a child email?
EDIT:
I could simply put the has_email boolean in a method like
def has_email?
if self.emails.count >0
return true
..
but i prefer the boolean in the attribute because i use it in many scope and it would be a lot a change in the app
This will ensure that your model has at least one email (place it in your model file place_detail.rb)
has_many :emails, :dependent => :destroy
validates :emails, :length => { :minimum => 1 }
EDIT:
One suggestion would be just to check the trait place_detail.emails count when you need it. If you examine such data multiple times a request you can store it like so
def has_email?
(result ||= self.emails.count) > 0
end
That way it will only check your database once
If you're forced to use the 'has_email' attribute within the place_detail model, you could simply save the place_detail in the Create method of the Email controller.
#email = Email.new(email_params)
#email.place_detail.save
I need validate the 'name' attribute of B class only when the attribute 'need_name' of A class is true. But I have a trouble with this validations.
My code:
class A
validates :need_name, presence: true
end
class B
validates :name, :presence => :need_name?
belongs_to :a
def need_name?
A.find(a).need_name
end
end
And my tests:
describe A do
context "validations" do
it { should validate_presence_of :need_name }
end
end
describe B do
context "validations" do
it { should validate_presence_of :name }
end
end
The test of class A works fine but I received this erro when I run the test of B class:
ActiveRecord::RecordInvalid:Validation failed: Need name can't be blank
The error disappears if I set true to the 'need_name' and I can't understand why this happens.
I really appreciate any help. Thank you guys.
Don't validate class A from within class B.
I'd validate the presence of the relation from class B, and then use validates_associated (described here) to trigger validations on A.
class A
validates :need_name, presence: true
end
class B
belongs_to :a
validates_presence_of :a
validates_associated :a
end
In the above code instances of class B will only validate if there's an association with a class A instance present and if the associated instance passes validation (i.e. has need_name set).
The solution was to change the way the validation is done to:
class A
validates :need_name, inclusion: { in: [true, false] }
end
class B
validates :name, :presence => { if: :need_name? }
belongs_to :a
def need_name?
a.need_name unless a.blank?
end
end
I have this model:
class CompetitionEntry < ActiveRecord::Base
has_many :participants
has_one :address
has_many :music_programs
accepts_nested_attributes_for :address
accepts_nested_attributes_for :participants, :music_programs,
:allow_destroy => true,
:reject_if => :all_blank
end
and this one:
class Participant < ActiveRecord::Base
belongs_to :competition_entry
has_one :birthplace
validates :name, :surname, :instrument, presence: true
end
Now the problem is that, if I create a new competition entry, it goes through.
But if I fill ONE field, i.e name, then it comes up with an error!
Why is this happening? It should fail when all are empty!
When you use accepts_nested_attributes_for, you are able to create the participants records at the same time that the competition_entry record, considering that the hash passed to competition_entry.create contains participants_attributes. When you pass only name, it validates the participant to be created and fail because it has no surname and instrument. When you leave all field empty, the behaviour should be the same, but it isn't because you explicitly set :reject_if => :all_blank.
:reject_if => :all_blank states that the participant_attributes hash should be ignored if it is blank?, which happens when you don't fill any field. What is happening then is that a competition_entry is being created without trying to create a participant because the accepts_nested_attributes_for is just ignored.
I want to impliment something which is similar to Twitter Repost System, therefore I will use this as an example. So let's say I have a Tweet Model and I want to allow other user to repost a certian tweet of another user, how do I impliment something like this?
I thought I would be a cool idea to put the retweet class into the tweet to be able to acess the repost too when I use Tweet.all to recive all tweets stored in the database, but somehow I didn't worked as expected...
The following Code is just an example which should show how to impliment this even if it is not working...
Any ideas how I could build a working repost model which also allows me to access both tweets and retweet by using Tweet.all?
class Tweet
class Retweet
include DataMapper::Resource
belongs_to :user, key => true
belongs_to :tweet, key => true
end
include DataMapper::Resource
property :text, String
property :timestamp, String
belongs_to :user
end
Important: I should be carrierwave compatible.
class Tweet
include DataMapper::Resource
property :id, Serial
has n, :retweets, 'Tweet', :child_key => :parent_id
belongs_to :parent, 'Tweet', :required => false
belongs_to :user
def is_retweet?
self.parent_id ? true : false
end
end
original = Tweet.create :user => user1
retweet = Tweet.create :parent => original, :user => user2
retweet.is_retweet? # => true