Model name appearing in my validation error in Rails - ruby-on-rails

I'm still struggling to get my validation error message to display without the name of the model appearing in it, I have a nested model called AnimalImage and am performing a validation on whether a file has been submitted.
def limit_num_of_images
if image.size < 1
errors.add(:base, "Please add an image")
ap(errors.inspect)
end
end
The error I get in this instance is:
Animal images base Please add an image
All I want to show is:
Please add an image
Looking in the console the output of errors.inspect is
"#<ActiveModel::Errors:0x007fa0192d1890 #base=#<AnimalImage id: nil, animal_id: nil, image: nil, created_at: nil, updated_at: nil>, #messages={:base=>[\"Please add an image\"]}>"
So the messages are in a hash? if that's the case I need to find a way of not displaying the key?
Finally in my view I am outputting the error messages like so
<% #animal.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
So as a quick fix I have created a helper that just strips out the first part of the text, but this feels too hacky and I would like to know how to do it properly with Rails:
def error_edit(message)
msg = message
msg.gsub('Animal images base', ' ')
end
// View
<% #animal.errors.full_messages.each do |msg| %>
<li><%= error_edit(msg) %></li>
<% end %>

I had the same problem in my controller. I know its not a better solution but I am sure it will give you an idea.
Please don't use
errors.add(:base, "Please add an image")
User this
errors.add(:attribute, "Please add an image")
<% #animal.errors.each do |key,value| %>
<li><%= "#{key.to_s.titleize} #{value}".html_safe %></li>
<% end %>

I think this will work for you
class Animal < ActiveRecord::Base
validate do |animal|
animal.errors[:base] << "Please add an image" if animal.image.size < 1
end
end
I will also suggest you looking at this link http://api.rubyonrails.org/classes/ActiveModel/Errors.html#method-i-add
Adds message to the error messages on attribute.
what you are doing is adding the message on an attribute called base, which is obviously not what you would like to have
update: add_to_base method was removed from rails 3. You should use errors[:base] << "error" instead.

Related

Hide/remove model name in association error message

For the life of me, I cannot find how to remove "model name" before the error message. Typically this would be ok but hear me out.
I have a model called 'foo'. I'd need to rename it at some point but for now it's a hassle. For now, I need to change the error message: "Foo How often you get paid is missing".
# finance.rb
belongs_to :foo # this will be renamed in the future
[..]
I thought I needed to edit the en.yml only:
en:
activerecord:
errors:
models:
finance:
attributes:
foo:
required: "How often you get paid is missing"
This works but I don't need to show the model's name with the message. Ok I could do some string replace but that's ugly. Is it possible to only show the message in the en.yml?
EDIT:
Error are displayed as:
<% if #finance.errors.any? %>
<ul>
<% #finance.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
Seems to be an easy solution found here. So in my case:
en:
errors:
format: "%{message}"
activerecord:
errors:
models:
finance:
attributes:
repayment_type:
required: "How often you get paid is missing"
This could be a duplicate post so you could mark as duplicate 🙂

How to use a button to post in rails?

So I'm trying to create a new "transaction" each time I click the button "Purchase", but doesn't seem to work. I get the error "undefined method `[]' for nil:NilClass".
<% #comics.each do |comic|%>
<ul>
<li><%= comic.title %> </li>
<li><%= comic.author %> </li>
<li><%= comic.year %> </li>
<li><%= comic.publisher %> </li>
<% if user_signed_in? %>
<%= button_to 'Purchase', {:controller => "transactions", :action => "create", :seller_id => comic.user_id, :buyer_id=> current_user.id, :comic_id => comic.id} , {:method=>:post} %>
<% end %>
</ul>
This is what you can find in the transactions controller:
def create
#my_transaction = Transaction.new(
buyer_id: params[:transaction][:buyer_id],
seller_id: params[:transaction][:seller_id],
comic_id: params[:transaction][:comic_id]
)
#my_transaction.save
redirect_to "/transactions/"
end
Do you have any idea why this might be happening?
Thanks!
There are a couple of ways you can debug this:
Look in the console logs to see what is being posted in the params hash.
add a puts statement at the top of the create statement to view what is in the params variable e.g.
controller
def create
puts params.inspect
end
I suspect you'll find that the params hash does not have a transaction key and the create method should be
def create
#my_transaction = Transaction.new(
buyer_id: params[:buyer_id],
seller_id: params[:seller_id],
comic_id: params[:comic_id]
)
end
The params[:transaction] is nil, you can see the sent parameters in the log (tail -f log/development.log if the server doesn't log). In your case you access the required data like params[:comic_id]
A few tips:
Never trust the input coming from the client:
:buyer_id=> current_user.id here an attacker could send any ID since the button_to helper will create a html form which is easily accessible using the devtool. Instead check it on the server side. Same goes for the seller_id, you can just fetch the related comic comic = Comic.find params[:comic_id].
You might want to consider an another API approach like POST /comics/1/buy this is a bit more restfull, and you could use the built in path helpers for that url like buy_comic_path(comic)

Saving a string with erb data in the model

I currently save code like below in my user model.
User.where(type: "supercool").each do |user|
if user.score == 100
user.message = "Hello #{user.name}, you now have #{user.points} points!".html_safe
elsif user.address == "New York"
user.message = "You live in the same town as #{Person.where(address:"New York").first.name}"
user.save
end
I save these messages in my model, and print them out in the view by just calling User.find(params[:id]).messages in the controller.
The actual model code is much longer, as there are many unique messages based on different scenarios.
While this works, I would now like to add a link_to to objects that are mentioned in the messages.
For the first message, I want to save it so that when I send it to the view, it's in the form of
Hello <%= link_to user.name, user_path(user.id) %>, you now have <%= link_to user.points, leaderboard_path %> points!
I tried the below, but it doesn't work.
User.where(type: "supercool").each do |user|
if user.score == 100
user.message = "Hello #{link_to user.name, user}, you now have #{link_to user.points, leaderboard_path} points!".html_safe
user.save
end
How can I save erb in my string?
How about this? Use html tags instead of using link_to
User.where(type: "supercool").each do |user|
if user.score == 100
user.message = "Hello <a href=#{Rails.application.routes.url_helpers.user_path(user)}>#{user.name}</a>, you now have <a href=#{Rails.application.routes.url_helpers.leaderboard_path}>#{user.points}</a> points!".html_safe
user.save
end
end
And in your view, Just do
<%= user.message %>
This is not a very good pratice.
You can like:
class Model < ActiveRecord::Base
include Rails.application.routes.url_helpers
def example
ActionController::Base.helpers.link_to user.name, user
end
end
But using a helper or a erb template to show this to the user seems the best way.

Error messages always include attribute name

I have the following validation error messages coming up when I try to submit a blank form:
Start time time Looks like you forgot the appointment start time.
Start time time Sorry, we can't understand "" as a time.
Start time ymd Please choose a date for the appointment.
Start time ymd Sorry, we can't understand "" as a date.
Stylist services Please choose at least one service.
These messages are for the following attributes:
start_time_time
start_time_time
start_time_ymd
start_time_ymd
stylist_services
I included the attribute names so you could plainly see which part of the error message is the attribute name.
How do I remove the attribute names from the error messages?
In rails 3.2.6, you can supress the inclusion of the attribute name by setting errors.format in a locale file (e.g., config/locales/en.yml):
en:
errors:
format: "%{message}"
Otherwise, the default format is "%{attribute} %{message}".
It's common to loop over object.full_messages to output each full message:
<% if object.errors.any? %>
<h2>Errors</h2>
<ul>
<% object.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
<h2>Errors</h2>
<ul>
<li>Start time time Looks like you forgot the appointment start time.</li>
<li>Start time time Sorry, we can't understand "" as a time.</li>
<li>Start time ymd Please choose a date for the appointment.</li>
<li>Start time ymd Sorry, we can't understand "" as a date.</li>
<li>Stylist services Please choose at least one service.</li>
</ul>
But a "full" message consists of the localized field name followed by the message (as you've seen; this is because the messages are usually things like "can't be blank"). If you just want the actual error message minus the field name, use the built-in each iterator instead:
<% if object.errors.any? %>
<h2>Errors</h2>
<ul>
<% object.errors.each do |field, msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
<h2>Errors</h2>
<ul>
<li>Looks like you forgot the appointment start time.</li>
<li>Sorry, we can't understand "" as a time.</li>
<li>Please choose a date for the appointment.</li>
<li>Sorry, we can't understand "" as a date.</li>
<li>Please choose at least one service.</li>
</ul>
You could use the i18n route to change the display name of the attribute.
config/locales/en.yml:
en:
activerecord:
attributes:
somemodel:
start_time_time: My Start Time Text #renamed text
stylist_services: "" #hidden txet
I did almost the same thing as Brandon.
First, I wrote a helper function for the object that the errors will render for.
#Remove unnecessary attribute names in error messages
def exclude_att(attribute, error_msg)
if attribute.to_s == "Put attribute name you don't want to see here"
error_msg
else
attribute.to_s.humanize + " " + error_msg
end
end
Then, in the view that has the form being validated, I did:
(Note: this is HAML code not HTML, but the tags are still the same so you can clearly see what I'm doing)
%h3= "#{pluralize(#user.errors.count, 'error')} prohibited this user from being saved:"
%ul
- #user.errors.each do |att, error|
%li= exclude_att(att, error)
That did it for me, no gems or third-party plugins.
-Demitry

Change error validation message in Paperclip

When you set a validation message in paperclip, such as
validates_attachment_presence, :image, :message => 'xxxx'
The custom message comes automatically prefixed with the name of the field, even though it has been overwritten with the :message . How do you totally override the message and make it totally custom?
Edit: typo
Not a real solution but a Easy one is to skip paperclip validation and write custom one.
validate :check_content_type
def check_content_type
if !['image/jpeg', 'image/gif','image/png'].include?(self.image_content_type)
errors.add_to_base("Image '#{self.image_file_name}' is not a valid image type") # or errors.add
end
end
I hope it can help
You actually want to do this inside your view rather than your model and it's actually quite straight forward. We're just going to loop through the errors, and when the one for your attachment comes up we'll ignore the field name:
<ul>
<% #myObject.errors.keys.each do |field| %>
<% #myObject.errors[field].each do |msg| %>
<% if field == :image_file_name %>
<li><%= msg %></li>
<% else %>
<li><%= field.to_s + " " + msg %></li>
<% end %>
<% end %>
<% end %>
</ul>
Replacing #myObject with the name of your model that should display only the message set to your attachment validation errors. This is just a simple example that displays them inline with the rest, but of course you could do anything you like with the messages. It's important to keep the name of the field that had the error in case you want to program any logic thats specific to its failure without having to rely on the error message staying exactly the same forever.
It's standard Rails behavior to show include the attribute name before the validation errors. You have a few options to work around this behavior:
Make your error message OK to have the attribute name prepended :)
Use a different error message formatter. It's pretty easy to write your own helper to iterate through an #object.errors and wrap messages in HTML tags. I prefer to use the error messages in-line near the fields so we always skip the attribute name.
Custom validation which adds the errors to base. This is easy, but wrong, since you're suggesting there's a validation error on a field. Still may solve your problem.
Override humanized_attribute_name for that attribute to hide it. humanized_attribute_name is probably used elsewhere, so this may cause other issues.
.
HumanizedAttributesOverride = {
:image => ""
}
def self.human_attribute_name(attr)
HumanizedAttributesOverride[attr.to_sym] || super
end
I don't know if it's just a typo inside your question, but it should be:
validates_attachment_presence :image, :message => 'xxxx'
And I would not use :message to add a custom error message, but put it inside a locales file.

Resources