What is the simplest way to make a field required in Rails?
inquiry.rb:
class Inquiry < ActiveRecord::Base
attr_accessible :address, :email_id, :gender, :message, :mobile_number, :name
end
You can use the presence validator:
validates :name, :presence => true
attr_accessible specifies a white list of model attributes that can be set via mass-assignment. This is meant to protect sensitive attributes from being overwritten by malicious users tampering with URLs or forms. It has nothing to do with validations.
So, if you want to make the attribute presence mandatory, you have to use a validation in your model, like this one:
validates :name, :presence => true
Related
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 am unable to use model.update_attribute on an attribute that is mounted by a carrierwave uploader. The SQL statement wont accept the value and adds NULL to the placeholder. If I remove the mount_uploader statement from the model class it works as normal. I am troubleshooting things from the console and trying to add some attributes while seeding the DB and this is thwarting my efforts. Ideas?
Thanks.
Update:
Relevant code:
class Profile < ActiveRecord::Base
belongs_to :user
has_and_belongs_to_many :sports
has_and_belongs_to_many :interests
has_and_belongs_to_many :minors
has_and_belongs_to_many :majors
has_and_belongs_to_many :events
has_and_belongs_to_many :groups
attr_accessible :description, :username, :avatar, :bio, :first_name, :last_name, :major, :minor, :graduation_date, :living_situation, :phone, :major_ids, :minor_ids, :sport_ids
mount_uploader :avatar, AvatarUploader
end
I am simply trying to rewrite the :avatar string from a db seed file and while testing from the rails console like so:
Profile.first.update_attribute(:avatar, 'foo')
Both work when I comment out the mount_uploader line.
Does adding the mount_uploader method freeze the string or make it immutable?
I found a solution to this.
My issue was that I was not able to alter the attribute mounted my the CarrierWave uploader from my seeds.rb file.
This works:
user.profile.update_column(:avatar, 'foobar/image.png')
I would like to have nice and clean structure in my Rails App.
Now I have 4 files in models folder: Post, PostTranslation, PostCategory and PostCategoryTranslation.
This is my post.rb
class Post < ActiveRecord::Base
attr_accessible :image, :image_cache, :remove_image, :post_category_ids, :post_categories_attributes, :post_translations_attributes
validates :post_translations, :post_categories, presence: :true
translates :name, :content
has_many :post_translations, dependent: :destroy
accepts_nested_attributes_for :post_translations, allow_destroy: true
end
This is post_translation.rb
class PostTranslation < ActiveRecord::Base
attr_accessible :locale, :name, :content
validates :name, length: { maximum: 255 }, presence: true
validates :content, :locale, presence: true
belongs_to :post
end
What should I do? What's the best practice? Make post folder and move translation into this folder and create sub model? Like this: class Translation < Post
Thanks for your advice
The main Best Practice here is to define your domain model properly, and this holds good regardless of Rails.
You need to decide what relation do Post and PostTranslation have with each other. If PostTranslation < Post, then belongs_to :post should probably not be there inside PostTranslation.
Once you have a clearer modelling, put all the classes in models folder itself.
I figured it out. I added namespace Blog..
Now I have these files
blog/post.rb - Blog::Post
blog/post/translation.rb - Blog::Post::Translation
blog/category.rb - Blog::Category
blog/category/translation.rb - Blog::Category::Translation
class Blog::Post < ActiveRecord::Base
validates :translations, :categories, presence: true
translates :name, :content
accept_nested_attributes_for :translations, allow_destroy: true
end
class Blog::Post::Translation < Globalize::ActiveRecord::Translation
validates :name, presence: true
validates :locale, presence: true, uniqueness: { scope: :blog_post_id }
end
I'm still getting my head around MongoDB and Mongoid in particlar.
Let's say I have a User and each User has one Thingamajig. When I create the User
I want the system to autmatically also create a blank Thingamajig for that User.
Each Thingamajig has a whatsit field that must be unique if it has a value, but is allowed to have no value when created.
So I define the following classes.
class Thingamajig
include Mongoid::Document
field :whatsit, type: String
index({whatsit: 1}, {unique: true, name: 'whatsit_index'})
end
class User
include Mongoid::Document
field :name, type: String
index({name: 1}, {unique: true, name: 'user_name_index'})
embeds_one :thingamajig, dependent: :nullify, autobuild: true
end
However what I find when I
User.create!(name: 'some name')
is that User.find(name: 'some name').thingamajig is nil.
Questions:
How can I ensure that each User gets an associated Thingamajig? and
How do I specify that the name field of a User is required?
FYI I am using Sintara not Rails (if that matters to anyone).
1 - The autobuild: true option normally should have done the trick. I think the problem is that you forgot to add the other side of the relation to the Thingamajig model:
class Thingamajig
include Mongoid::Document
embedded_in :user
...
end
2 - To specify required fields, use validations:
class User
include Mongoid::Document
field :name, type: String
validates_presence_of :name
...
end
Mongoid uses ActiveModel validations.
I want to implement before_validaton callback in a separate class so that it can be reused by multiple model classes.
Here in callback i want to strip field passed as parameter but i am not sure how to pass parameter to callback class. Also i want to pass this as reference rather than by value(not sure if this concept is in Ruby Rails). I am following the link http://guides.rubyonrails.org/active_record_validations_callbacks.html#callback-classes
Here is code which is not completely correct, please help for same
class StripFieldsCallback
def self.before_validation(field)
field = field.strip
end
end
class User < ActiveRecord::Base
validates_uniqueness_of :name, :case_sensitive => false
validates_length_of :name, :maximum => 50
before__validation StripFieldsCallback(name)
end
If i define method in model in itself rather than defining in separate callback class code is like this (which works fine)
class User < ActiveRecord::Base
validates_uniqueness_of :name, :case_sensitive => false
validates_length_of :name, :maximum => 50
before__validation :strip_blanks
protected
def strip_blanks
self.name = self.name.strip
end
end
Of course it is not good to replicate methods in all of models so i want to define method in callback classes.
You may do this or use normalize_attributes gem
module StripFieldsCallback
def before_validation_z(field)
write_attribute(field, read_attribute(field).strip) if read_attribute(field)
end
end
class User < ActiveRecord::Base
include StripFieldsCallback
before_validation lambda{|data| data.before_validation_z(:name)}
end