I want the sign up form on my site to have a field that takes the sum of a math equation and use rails validation to validate it. Whats the best way to do it?
i.e
What is 6 + 9 ? [ 8 ]
Error Message : You have entered the wrong number
Override the validate method in your model class. Remember that the model object you create for the new action is a different instance than the one created for the create action, so you'll need to save the random seed or the math expression somewhere in your form so that you can recreate it during validation.
Then, something along the lines of:
def validate
unless math_equation_answered?
errors.add("math_answer", "is incorrect")
end
end
The implementation of math_equation_answered? is up to you, and math_answer should be changed to whatever model field you use for the user's answer.
Related
I'd like one of my models, Stones, to be generated at random using pre-defined options I've stored in a set of arrays and hashes. Instead of Create using params from the URL, I'd like new Stones to always be defined using this random generation process. I don't need any user input at all, except that each stone belongs to a given player.
I'm still new to rails; where should I put all this code? I know enough to be able to define the arrays and hashes and randomly select from them when I need to, but I'm not sure where and how to replace the part of the code that draws params from URLs and fills in a new record before it is saved. I know controllers are supposed to be skinny, so do I do this in the model?
Apologies if this is a duplicate. I searched extensively and couldn't find an applicable solution.
Thanks for any help!
I would create a service for this. Something like:
# app/services/stone_creator.rb
class RandomStoneCreator
RANDOM_FOOS = ['bar', 'baz', 'bat']
def self.call(user)
Stone.create!({
foo: RANDOM_FOOS.sample,
user: user
})
end
end
And then anywhere that you need a new random stone you can call it like:
random_stone = RandomStoneCreator.call(current_user)
I have a model called Post in my Rails 3 app.
Users can create their own urls for these posts. (I call this a clean_url.)
If the user does not complete this field, I want to create the value myself from the title upon saving the form. (Essentially use the #post.title.to_s(some reg ex to remove spaces etc...)
What is the best approach to having the item save with title value in this field if it is left blank?
I assumed in the Posts controller create action I could "update_attributes" of the post upon saving... but Im beginning to think maybe this is wrong?
Anyone have ideas on how to achieve this?
Use a before_save callback, and a private method in your model. The following is taken straight from my blog source.
before_save :create_clean_url
private
def create_clean_url
if self.clean_url.blank?
# Remove non-alpha characters. Replace spaces with hyphens.
self.clean_url = self.title.downcase.gsub(/[^(a-z0-9)^\s]/, '').gsub(/\s/, '-')
end
end
I use a series of named scopes on a model to generate a query.In that query there's a join with another table in which I have some boolean fields.
When I access the values of those columns it returns strings("0" and "1").
Is there a DRY way to tell the model how to interpret those columns?(I know i can write methods to override the accesor, but that doesn't feel right).
I'm using rails 2.3.8.
If by "override the accessor" you meant read_attribute and write_attribute methods, then this is absolutely the correct way to do this. Rails type casts fields automatically and AFAIK there is no direct way to influence type casting, only overriding setters/getters.
For integrity's sake, an example:
def admin_user
read_attribute(:admin_user) == "1" ? true : false
end
def admin_user(v)
write_attribute(v ? "1" : "0")
end
Note: for more complex cases (say password encryption) the best way would be ActiveRecord Callbacks. Take a look at the examples there.
Say I have a model called User that has the following parameters: favorite_color, favorite_animal, and lucky_number. The user fills in the form containing only favorite_color and favorite_animal. When the form is submitted, I want to run a function that takes the color and animal into account and comes up with a lucky_number. How do I insert a value to the post values without the user filling out the form - how and where do I implement this?
Thank you!
Since the lucky_number won't be known until after the favorite_animal and favorite_color are already recorded, it would be impossible to send it along with the post request. Try using a
before_validation_on_create
that looks something like this:
before_validation_on_create :generate_lucky_number
def generate_lucky_number
self.lucky_number = self.favorite_animal.length + self.favorite_color.length
end
This function just sets the lucky number to the combined length of the strings stored for the favorite color and favorite animal, and will set it before saving the user to the database.
You could build it into your controller logic, or place the code in your model in one of the following callbacks:
before_validation
before_validation_on_create
before_validation_on_update
In the current app I'm building I've got a textarea where a user will enter a comma-delimited list of email addresses.
I'm currently splitting the list into an array and then saving one by one. But if, say, I have this input...
blah#example.com, test#example, foo#example.com
... then blah#example.com will be saved, but saving test#example will fail. So I then need to remove blah#example.com from the comma-delimited string of values that I pass back to the textarea when I show the error that test#example isn't a valid email address.
Is there a better way to validate these on the server side and handle errors without getting fancy / ugly in the controller?
Thanks in Advance!
Assuming this is a model that has_many emails, and the email model uses :validate_email, you could do something like the following:
class Foo < ActiveRecord::Base
validate :must_not_have_invalid_addresses
...
def emails=(addresses)
#invalid_addresses = []
addresses.split(",").each do |address|
#invalid_addresses.push(address) unless emails.create({:address => address})
end
end
def must_not_have_invalid_addresses
errors.add_to_base("Some email addresses were invalid") unless #invalid_addresses.empty?
end
end
This provides a validation error + an array of the invalid email addresses which you can make accessible to your view if you like.
ruby has a split function (.each) described here and supports regular expressions as described here
as such, you'd split the string (using "," as your separator) and then use the regular expression to validate each e-mail.
You can put saving emails in transaction. Then if any save will fail, then all previos saves are canceled. In such case, validations can be done only on model layer.
I think it would be clear code, but for sure it isn't the fastest possible way (but using Ruby means you are not doing it in even fast way ;) )
If you have them in a variable called emails, perhaps something like this may work:
if valid_emails?(emails)
# then have your normal logic here
if #user.save
flash[:notice] .....
end
end
private
def valid_emails?(emails)
not emails.find {|email| email =~ /[\w\.%\+\-]+#(?:[A-Z0-9\-]+\.)+(?:[A-Z]{2,}|com|org|net|edu|gov|mil|biz|info|mobi|name|aero|jobs|museum)/i }.nil?
end
EDIT: actually you may just want to use this regular expression. It was taken from the restful-authentication plugin.