Skip validates_presence_of from a belongs_to association - ruby-on-rails

I'm trying to skip validations of a belongs_to association if a criteria is true. Below is my code
class Venue < ActiveRecord::Base
has_many :events
validates_presence_of :name, :postcode, :category
end
class Event < ActiveRecord::Base
belongs_to :venue
accepts_nested_attributes_for :venue
end
So what I need to do is skip the Venues validates_presence_of validation if a criteria from the Events model is true. So lets say if the event_type was equal to '1' then it will ignore the Venues validates_presence_of call but if event_type was '2' then it will still execute the validates_presence_of call.

There's a Railscast on this topic. You can also check out Rails Conditional Validation
based on the link above, you'll have to pass a lambda such as:
:if => lambda { |venue| venue.event.try(:event_type) == 2 }

In the end I did something very similar to this

Related

find_or_create on a has many through relationship

I have a has many through relationship in my app:
Shows has many Bands through => Lineups
Bands are unique by :name
class Show < ActiveRecord::Base
attr_accessible :city_id, :title, :dateonly, :timeonly, :image, :canceled, :venue_attributes, :bands_attributes
belongs_to :city
belongs_to :venue
has_many :lineups
has_many :bands, through: :lineups
has_and_belongs_to_many :users
end
class Lineup < ActiveRecord::Base
belongs_to :show
belongs_to :band
end
class Band < ActiveRecord::Base
attr_accessible :name, :website, :country, :state
has_many :lineups
has_many :shows, through: :lineups
validates :name, presence: true
validates_uniqueness_of :name
before_save :titleize_name
private
def titleize_name
self.name = self.name.titleize
end
end
New Bands are created like this:
(lets say we have a show record already saved called s1)
> s1.bands.new(name: "Wet Food")
> s1.save
Right now this will only save if a band named "Wet Food" doesn't already exist
In which model is the best place to do a Band.find_or_create in this relationship so that an existing band can be used if one with the same name exists?
This is generally the type of call that would go in a Controller (or maybe a service object), but not in a Model. It really depends on the particular user flow that you're trying to accomplish in your app. Basically, where ever you are already using s1.bands.new, you could use this instead :
s1.bands.where(name: 'Wet Food').first_or_create

Testing association through aliases

I'm new to TDD and Rails.
I'm trying to test an 'aliased' association (don't know if this is a valid term).
My test:
it 'an order should always have a customer' do
o = Order.new
o.should_not be_valid
end
My model:
class Order < ActiveRecord::Base
belongs_to :customer, :class_name => Person
validates_associated :customer
end
I don't know if validates_associated does what It implies. My test still counts orders with 'custumer_id: nil' as valid.
The Person model:
class Person < ActiveRecord::Base
attr_accessible :first_name, :last_name, :middle_name
validates_presence_of :first_name, :last_name
has_many :addresses
has_many :orders, :as => :customer
end
I want to make sure that every Order saved has an associated custumer (a Person object).
Am I missing something?
validates_associated only tells the Model that validations should be run on associated objects as well (have a look at the docs here). You still need to add a validation on Order. Have a look at this SO question. I could be wrong, but I think it will point you in the direction of what you're looking for.

Has-Many and Belongs-to-one Relation

I'm trying to keep track of how many signup_conversions a user creates.
Therefore, I have those two following models:
signup_conversion.rb
class SignupConversion < ActiveRecord::Base
belongs_to :user
belongs_to :convertee, :class_name => "User", :foreign_key => 'convertee_id'
attr_accessible :convertee_id
end
user.rb
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation
belongs_to :signup_conversion
has_many :signup_conversions
end
Would this work that way? Or am I missing something crucial here?
I haven't tried the code, but I give you some tips that hope you find useful.
I think every has_many/has_one statement should have its correspondent belongs_to, so three belongs_to and one has_many doesn't look good.
I'm not sure has_one :signup_conversion and has_many :signup_conversions would play well together, so I'd rather change the names. I changed the other names as well to try to make the associations clearer although I'm not sure I fully understand the real concepts they represent. You will probably come up with better names.
By default, the foreign key is guessed adding the suffix _id to the association name, so you don't need to specify it in this case. Also, I don't think you need to make that attribute accessible, at least not for the association to work.
signup_conversion.rb
class SignupConversion < ActiveRecord::Base
belongs_to :owner , :class_name => "User"
belongs_to :convertee, :class_name => "User"
end
user.rb
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation
has_one :owned_signup_conversion , :class_name => "SignupConversion"
has_many :triggered_signup_conversions, :class_name => "SignupConversion"
end
You have more code than you need here; you only need
class SignupConversion < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation
has_many :signup_conversions
end
Then you need a user_id column in your signup_conversions table, and you call
#user.signup_conversions
in your views or controller.

validating a belongs_to association

I'm trying to validate a model Student like this;
class Student < ActiveRecord::Base
belongs_to :room
end
I want to ensure that Room is a valid model, and with that I can only save a student only if the room is valid.
I tried to change the association to:
belongs_to :room, :validate => true
But it didnt change the behaviour..
API says:
:validate
If false, don’t validate the associated objects when saving the parent object. false by default.
So I changed the validation to room:
class Room < ActiveRecord::Base
has_many :students, :validate => true
end
but neither options solve for me
any ideas???
Give this a try...
class Student < ActiveRecord::Base
belongs_to :room
validates_associated :room
end
I'm looking at this portion of the API docs: http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#method-i-validates_associated
Also, be careful not to use that validation on both sides of the association!

Validating a self-referential association doesn't link back to the original instance in rails

I have a many-to-many model, following the example in this great railscast
My model links authors to each other. I'd like to validate that an author cannot friend himself. I know I can handle this at the UI level, but I'd love to have a validation in place to prevent a bug in the UI from allowing it. I've tried validates_exclusion_of, but it doesn't work. Here's my model for the relationship:
class Friendship < ActiveRecord::Base
# prevent duplicates
validates_uniqueness_of :friend_id, :scope => :author_id
# prevent someone from following themselves (doesn't work)
validates_exclusion_of :friend_id, :in => [:author_id]
attr_accessible :author_id, :friend_id
belongs_to :author
belongs_to :friend, :class_name => "Author"
end
You'll have to use a custom validation:
class Friendship < ActiveRecord::Base
# ...
validate :disallow_self_referential_friendship
def disallow_self_referential_friendship
if friend_id == author_id
errors.add(:friend_id, 'cannot refer back to the author')
end
end
end

Resources