validate count of created has_many objects in rails 3.2 - ruby-on-rails

Validate count of created has_many objects in rails 3.2?
I need a custom validation for "max/min" count of associated object.
I have Realty, that has
has_many :realty_images, :dependent => :destroy
accepts_nested_attributes_for :realty_images
and realty_image:
class RealtyImage < ActiveRecord::Base
attr_accessible :avatar, :image, :realty_id
belongs_to :realty
#here a suppose I need to put some kind of custom validation
mount_uploader :image, ImageUploader
end

The standard validation methods work well with associations:
class Ad
has_many :realty_images
# make sure there are some images
validates_presence_of :realty_images
# or make sure the number of images is in certain range
validates_length_of :realty_images, within: 5..10
end
Check out documentation for more details.

Not sure if I totally understood, but if you try to limit the number of realty_images of a given realty, and assuming that realty.maximum contains the max limit for that given realty:
In RealtyImage model:
class RealtyImage < ActiveRecord::Base
attr_accessible :avatar, :image, :realty_id
belongs_to :realty
validate :maximum_number_of_realty_images
mount_uploader :image, ImageUploader
protected
def maximum_number_of_realty_images
errors.add(:base, "Maximum reached") unless realty.realty_images.count < realty.maximum
end
end

Related

How to associate attributes from different classes Rails

I'm facing a difficult to associate things on Rails. In this case, I have a model for locals, and a model to identifier a user token ( that came from another APi). A place has a rating ( a score from 0 to 5 ) associated with it, and every user has many ratings but just one for each place. Trying to do this I create a new model that has ratings attribute and I want to associate a rating id to just one place id.
# Description of User Identifier Class
class UserIdentifier < ApplicationRecord
has_many :favorite_locals, dependent: :destroy
has_many :user_rate, dependent: :destroy
validates :identifier, presence: true
validates_numericality_of :identifier
validates_uniqueness_of :identifier
def self.find_favorites(params)
UserIdentifier.find(params).favorite_locals
end
end
# Model of Users Rates
class UserRate < ApplicationRecord
belongs_to :user_identifier
validates :rating, numericality: true
validates_numericality_of :rating, less_than_or_equal_to: 5
validates_numericality_of :rating, greater_than_or_equal_to: 0
validates :user_identifier, presence: true
end
First, you have a typo in the has_many :user_rate, dependent: :destroy. The association should be named user_rates, so the correct code for UserIdentifier model is:
class UserIdentifier < ApplicationRecord
has_many :favorite_locals, dependent: :destroy
has_many :user_rates, dependent: :destroy
# ...
end
Second, it's not clear how the "place" entity is named in your project. If it's FavoriteLocal then this is the code you need:
class UserRate < ApplicationRecord
belongs_to :user_identifier
belongs_to :favorite_local
# ...
end
If this is another model just define the belongs to association right below belongs_to :user_identifier. I hope you got the idea.

How does activerecord change model associations in rails?

I at one point had a simple model where a recipe had many photos, yet I was only creating Recipe objects by setting one photo through carrierwave on the recipe.photo attribute rather than through recipe.photos.
This was in part because I didn't realize I had specified has_many. I was creating Recipe objects through rails_admin gem by assigning to the recipe.photo attribute rather than recipe.photos.
class Recipe < ActiveRecord::Base
validates :title, :content, presence: true
belongs_to :category
has_many :photos, class_name: 'RecipePhoto', dependent: :destroy
mount_uploader :photo, RecipePhotoUploader
accepts_nested_attributes_for :photos, allow_destroy: :true
end
class RecipePhoto < ActiveRecord::Base
belongs_to :recipe
mount_uploader :photo, RecipePhotoUploader
end
So my question is when I began assigning to recipe.photos and then were to access a recipe instances photos via recipe.photos
I would only see photos that were created onto recipe.photos, and not recipe.photo.
Why is this? Shouldn't ActiveRecord access ALL associated photos to the recipe with notation recipe.photos?
Why does it treat it as recipe.photo were assigned via a has_one relationship even though it was has_many the whole time?
Shouldn't ActiveRecord be robust to changing relationships? Like if it at a later date and wanted to change it to has_one, etc.

has_one polymorphic association select_box

Hi I have problem with make working select_box with has_one association.
I have model image_element which is polymorphic:
class ImageElement < ActiveRecord::Base
belongs_to :imageable, polymorphic: true
belongs_to :image
end
model image:
class Image < ActiveRecord::Base
attr_accessible :image, :application_id
belongs_to :application
has_many :image_elements, as: :imageable
mount_uploader :image, ImagesUploader
end
and model level which has got following association:
has_one :image_element, as: :imageable
has_one :image, through: :image_element
accepts_nested_attributes_for :image_element
In the level form I'm trying to create the select_box to select an image_element for level.
= f.select(:image_element, ImageElement.all.collect{|i| i.image.image.thumb})
Select box is viewing properly but when i submit the form i have the following output from the server:
WARNING: Can't mass-assign protected attributes: image_element
Thank's in advance :)
Try adding image_element_attributes to attr_accessible
attr_accessible :image, :application_id, :image_element_attributes

How presence works in rails

I was reading validation from http://guides.rubyonrails.org/active_record_validations.html . I understand that presence checks whether given attribute is either empty or consists of whitespace. But what I don't understand is that, how to test association is present. They showed two example
class LineItem < ActiveRecord::Base
belongs_to :order
validates :order, presence: true
end
and
class Order < ActiveRecord::Base
has_many :line_items, inverse_of: :order
end
I understand the code here but I don't understand how it test association.
LineItem has order_id and that is what being validated. it is simply checking if that field/column has a value.

Dynamic Store Dir with CarrierWave

Only new to Rails but I've started been using CarrierWave for my upload handling. I am trying to make a media hosting app whereby:
A Show belongs to a User
A Show has many Episodes
An episode belongs to video
At the moment I am using single table inheritance to store my video content into a meta data type Asset table, all is saving well. The issue I'm trying to get to is when I save the video via CarrierWave I want to be able to get both the show slug and the episode slug into the save path.
Currently I have this set up with my shows and episode uploads:
def store_dir
"shows/#{model.friendly_id}/cover/"
end
And previously before STI i would just store the filename in a video field in the episodes table and have it store via:
def store_dir
"shows/#{model.show.slug}/episodes/#{model.id} - #{model.friendly_id}"
end
Only problem now I cannot get the episode information from my video model in the CW uploader.
My models are:
Show.rb
class Show < ActiveRecord::Base
#Associations
belongs_to :user
belongs_to :category
has_many :episodes
#Slugs
extend FriendlyId
friendly_id :title, use: :slugged
#Carrierwave
mount_uploader :image, ShowImageUploader
end
Episode.rb
class Episode < ActiveRecord::Base
belongs_to :show
belongs_to :image, :class_name => "Episode::Image"
belongs_to :audio, :class_name => "Episode::Audio"
belongs_to :video, :class_name => "Episode::Video"
accepts_nested_attributes_for :video, :image, :audio
before_save :add_guid, :on => :create
#Slugs
extend FriendlyId
friendly_id :title, use: :slugged
validates :title, :presence => true, :length => {:within => 5..40}
protected
def add_guid
self.guid = UUIDTools::UUID.random_create.to_s
end
end
episode/video.rb
class Episode::Video < Asset
mount_uploader :video, EpisodeVideoUploader, :mount_on => :filename
end
asset.rb
class Asset < ActiveRecord::Base
end
So I guess how can I get the appropriate data after upload into:
"shows/#{model.show.slug}/episodes/#{model.id} - #{model.friendly_id}"
Thanks!

Resources