Errors Messages, keep showing InValid - ruby-on-rails

In my Rails CREATE controller for a model, if the name of the record already exists, via JS I'm outputting the following response:
<%=#space.errors%>
Which outputs:
permissionsis invalidnameThis project name is already in use
In the model I have:
validates_uniqueness_of :name :message => 'This project name is already in use'
How do I get rid of the noise: "permissionsis invalidname" for the life of me I can't find it in the docs? Apologies if I'm missing something hugely obvious.

The issue is that you are actually returning the array containing all the error objects.
What you actually want is:
<ul>
<% #space.errors.full_messages.each do |msg| %>
<li><%=h msg %></li>
<% end %>
</ul>
This will give you a list of the errors.
I'm also pretty sure there's a nicer way to do this (i.e. some sort of helper built in to rails), but I haven't been able to find it in the docs for rails 3.

Related

How do I group objects returned by a REST API based on a value inside that object?

I'm pretty new to ruby/rails so bear with me.
I'm attempting to take the results returned by the JIRA rest API and render them in a view. I can do that pretty easily using the jira-ruby gem. The problem I'm having is grouping the results by a specific object inside the object returned by the API (in this case, a "components" field object inside of a "issue" object). I've attempted to use group_by and chunk for this but I'm basically getting the inverse of what I want. Both methods return the same result.
In my controller I have:
#issues = #jira_client.Issue.all
In my view I have:
<% #issues.chunk {|issue_comp| issue_comp.fields["components"]}.each do |comps, issues| %>
<h2>
<% comps.each do |comp| %>
<%= comp["name"] %>
<% end %>
</h2>
<ul>
<% issues.each do |issue| %>
<li><p><%= link_to issue.key, "http://localhost:2990/jira/browse/#{issue.key}" %> - <%= issue.summary %></p></li>
<% end %>
</ul>
<% end %>
What I end up with is:
CompA CompB
IssueA
CompC CompD
IssueB
CompA CompC CompD
IssueC
etc.
What I want is:
CompA
IssueA
IssueC
CompB
IssueA
CompC
IssueB
IssueC
CompD
IssueB
IssueC
The object returned by the API is a pretty convoluted object (i.e. giant array of hashes inside arrays inside of hashes). So, I have to dig pretty deep to get at the component name.
I get the feeling that this shouldn't be as complicated as it seems but I have a terrible habit of making things more complicated than they need to be. What am I doing wrong here?
EDIT: I created a gist of the full dump that is returned with the above call. Notice the "components" array:
jira-ruby gem dump for all issues
I took a look at the data you're getting back from Jira. This is how it looks to me:
There is an outer array of Jira Issues.
Each issue has an "attrs" hash
Each "attrs" hash contains components.
If this understanding is correct, I think you are attempting to invert that structure so that you can get a complete list of components, then iterate over each of them, and show the Issues that belong to that component.
If that understanding is correct, you have two basic choices:
Check if you can ask Jira for that information (so you don't have to generate it yourself), or
Build your own data structure (in memory on in a local DB as you prefer):
Some sample code for building a useful structure in-memory:
# in a controller, model, or service class (as you wish)
#components = {}
#jira_issues_array.each do |jira_issue| # from your API call
jira_issues[:components].each do |jira_component|
#components[jira_component[:key]] ||= { name: jira_component[:name], issue_keys: [] }
#components[jira_component[:key]][:issue_keys] << jira_issue[:key]
end
end
In your view, you could iterate over #components like this:
# some html.erb file:
<h1>Components and Issues</h1>
<ul>
<% #components.keys.each do |component_key, component| %>
<li><%= component[:name] %>
<ul> <!-- nested -->
<% component[:issue_keys].each do |issue_key| %>
<%= #jira_issues_array.find { |issue| issue[:key] == issue_key }[:name] %>
<% end %>
</ul>
</li>
<% end %>
</ul>
Note: Like a typical lazy programmer, I haven't tried this out, but it's really intended to show how you might go about it. For example, each issue's name is embedded in the attrs section, so you'll need to dig that out a bit.
Finally, if anyone would find this useful, I use this to analyse and reformat JSON.
HTH - any questions or problems, post a comment.

Rails 3 - get full error message for one field

I have user.errors which gives all errors in my controller. So, i have the field :user_login which has its error(s). How can i get full error messages from user.errors ONLY for that field?
I can get just text of this field like that:
user.errors[:user_login] # Gives that 'can't be empty'
But i really want to do something like that
user.errors.get_full_message_for_field[:user_login] # 'Your login can't be empty'
Well, I know this question was explicitly posted for Rails 3.x, one and a half years ago, but now Rails 4.x seems to have the very method you were wishing, full_messages_for.
user.errors.full_messages_for(:user_login) #=> return an array
# if you want the first message of all the errors a specific attribute gets,
user.errors.full_messages_for(:user_login).first
# or
user.errors.full_messages_for(:user_login)[0]
It's less verbose than the previously used user.errors.full_message(:user_login, user.errors[:user_login].first).
Have a look at full_message here:
http://api.rubyonrails.org/classes/ActiveModel/Errors.html#method-i-full_message
A bit verbose but you may be able to do something like:
user.errors.full_message(:user_login, user.errors[:user_login])
We can get the error message of particular field by using
<%= resource.errors.full_messages_for(:email).join("") %>
output : Email cant be blank
If you want to check the particular field has error or not then check it by using
resource.errors.include?(:email)
output : true/false
Here is the code snippet for displaying only the first error for each field.
<!-- Display only first error for each field --->
<% entity.attributes.keys.each do |key| %>
<% if entity.errors.full_messages_for(key.to_sym).length > 0 %>
<li><%= entity.errors.full_messages_for(key.to_sym).first %></li>
<% end %>
<% end %>

Ruby On Rails - "undefined method `id' for 4:Fixnum"

I recently decided I wanted to list all the users in my Ruby On Rails application - since I couldn't figure out how to list them any other way, I decided to use partials.
I have the following on my administration page (just hooked up to a its own administration controller):
<%= render :partial => User.find(:all) %>
I then have a file called _user.html.erb in my users view folder. This contains the following:
<ul>
<% div_for #user.object_id do %>
<li><%= link_to user.username, user.username %></li>
<% end %>
</ul>
When the application runs and I go to the administration page, I get the following error:
undefined method `id' for 4:Fixnum
It says it's because of this line (which is in the partial file):
<% div_for #user.object_id do %>
I'm unsure why this happens (and have googled for hours to try and find results and only find solutions that don't work for me). I think it's something to do with my usage of the #user instance variable, but I'm not totally sure.
You get that error because div_for expects an active record object as an argument, which it calls the id method on. You pass in a fixnum (the result of #user.object_id), which is not an active record object and does not have an id method.
So pass in #user instead of #user.object_id and it will work.
Also you should use user instead of #user, rails 3 does not set instance variables for partials anymore.
Lose the .object_id part. I seriously can't think why are you using object_id!Do you have a good reason for doing so? Anyway div_for wraps a div around an object, so leave the .object_id part!
instead of object you are using it's column or visa varsa you are using at that time you will get this kind of error.
Example
I am using id instead of user = User.first object.
Try this, it worked for me.
#item.unit_of_measure.name
instead of
#item.unit_of_measure_id.name

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.

Rails Model-Association Form Question

Hey guys, I'm having trouble understanding a Rails construct. I'm using Rails 3 but I doubt this is specific to this version.
I have a model, Goal that has_many :commits and naturally, a Commit model that belongs_to :goal. I created the proper migration so that commits_table.references :goal.
I am actually going through the Rails Getting Started guide, except in that article they use a Post and Comment respectively.
Now that I've described the situation I can express my confusion. On the Goal's show view, I have embedded a form to create a new Commit which is 'attached' to the currently viewed Goal. This works fine and all. However, I am having trouble understanding why we do this
<%= form_for([#goal, #goal.commits.build]) do |f| %>
Shouldn't it be form_for(#commit)? I understand why we want the #goal, to provide some context since the commit is a nested resource. However, in the actual generated source, the form is appropriately named as commit, that is, the fields are named commit_blah. How did Rails know this? I understand that there's this whole system of "trust and magic" and all, but I mean at least at the high level, what from this code hinted to Rails that I wanted a commit?
I looked at the documentation for form_for and it seems like one of the parameters could be the action to take for the form. I imagine that in this case, that's what the #goal.commits.build parameter is for? To designate the action to take? Is this how Rails deduces that I want a commit? Would this also explain why this form is handled by the Commit controller even though this code is in the Goal's view?
Also, why are these parameters passed as an array ([])? In Ruby, will the method still just take it as two separate parameters, or is there a reason why this was passed this way?
Finally, rails generate automatically gave me some error showing code in my other _form.html.erb partials:
<% if #commit.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#commit.errors.count, "error") %> prohibited this commit from being saved:</h2>
<ul>
<% #commit.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
If I want to add this to this embedded form, how would I do so? I guess my question is, what would I use in place of #commit?
Thanks. I'm just trying to get my head around these new concepts.
If you go back to the documentation and click 'show source', you'll see
def form_for(record_or_name_or_array, *args, &proc)
...
case record_or_name_or_array
when String, Symbol
...
when Array
object = record_or_name_or_array.last
object_name = options[:as] || ActiveModel::Naming.singular(object)
apply_form_for_options!(record_or_name_or_array, options)
args.unshift object
else
...
end
...
output << fields_for(object_name, *(args << options), &proc)
...
For form_for, the first parameter can be a record, name or an array. In your case, you pass it an array. The code then determines the 'object' as the last member of that array, which is your #goal.commits.build object. The object name is determined from the ActiveModel::Naming.singular method.
console > ActiveModel::Naming.singular(#goal.commits.build)
=> "commit"
Then it generated the appropriate form fields using fields_for and 'commit'.
It looks like you are using nested resources. Check your routes.rb file to see if you have something like:
map.resources :commits, :has_many => :goals
or perhaps:
map.resources :commits do |commit|
commit.resources :goals
end
If that is the case, then you will need to supply both the commit and goal objects to the form_for method.

Resources