I am trying to display validation errors in the view. When i try to save this the error is raised both in the view and logs instead with my custom message additional filter type is required
Here is my code
Model
class AdditionalFilter < ActiveRecord::Base
validates :additional_filter_type, presence:{ message: "additional filter type is required" }
end
View
<% if #form.errors.any? %>
<%= #form.errors%> <!-- i know should just display an array -->
<%end%>
I am using Rails 4. Any help will be appreciated, or even guidance how to debug this.Thank you
Here is the error in the log
ActiveRecord::RecordInvalid - Validation failed: Additional filters additional filter type additional filter type is required:
activerecord (4.2.3) lib/active_record/validations.rb:79:in `raise_record_invalid'
activerecord (4.2.3) lib/active_record/validations.rb:43:in `save!'
You're using save!, which raises an exception, which will skip your view entirely. You should be using save, and allowing the invalid record to "fall through" to your view.
Related
I am trying add a fake input to simple_form using the following suggestion (rails simple_form fields not related to the model), but it does not work for me.
This is my HAML code for adding a fake input field.
= f.input :agrees_to_terms, :as => :fake
I put the following class in app/inputs/fake_input.rb
class FakeInput < SimpleForm::Inputs::StringInput
# This method only create a basic input without reading any value from object
def input
template.text_field_tag(attribute_name, nil, input_html_options)
end
end
I get the following runtime error
No input found for fake
I have two initializers that were generated by Rails Composer: simple_form.rb and simple_form_bootstrap.rb
How can I make Rails find my FakeInput class?
I had the same issue, and a server restart resolved it.
I would like to show some extra info in error messages resulting from a failed validation. For example suppose I have a class Book with the following validation
validates :name, presence: true, uniqueness: true
When someone tries to insert a book by the same name the following error message is returned
{"name":["has already been taken"]}
Instead I wanna show
{"name":["Book 'Great Expectaions' has already been taken at id:7"]}
Right now to make this happen I have to remove the uniqueness validation that I mentioned above and do the following
validate do |book|
existing_book = Book.find_by_name(book.name)
if existing_book
book.errors.add(:name, "#{existing_book.name} already exists at id: #{existing_book.id}")
end
end
Is there a way to get custom error messages like above without writing a custom uniqueness validation? I was thinking something along the lines of
validates :name, presence: true, uniqueness: {message: "#{self.name} already exists at id: #{Book.find_by_name(self.name).id}"
But this does not seem to work as self.name returns 'Book'. Is there a way to access the passed parameters in this context?
You'll have to do this as a custom validation. I would do it like so:
validate :name_is_unique
private
def name_is_unique
errors.add(:name, "#{other_book.name} already exists at id: #{other_book.id}") if other_book = Book.find_by_name(name)
end
The issue isn't really that you can't include the current model attributes in your validation, its that there's no 'one-liner' way to include another model. The good news is, that's what the validate method is for.
If it bothers you to have this in your model, just write a custom validator so it can be re-used application-wide.
I am doing an online contract agreement which is generated dynamically based on the current state of our contract language (stored in an ERB partial).
When the user clicks "I Agree" we save the variable data, but I also want to store the contents of the rendered partial (html fragment) in the database.
I tried using ActionView::Helpers::CaptureHelper.capture -- wrapping the whole partial in a block and rendering at the end, like
<% #saved_output = capture do %>
...
The rest of the erb with instance variable <%= #my_class.name %> and so on
...
<% end %>
<%= #saved_output %>
<% logger.debug "Rendered output is: #{#saved_output}" %>
And this produced the same result and also sent the correct text to the log. But it appears to go out of scope -- even if I declare #saved_output = nil prior to render it's nil when I end the block.
I tried using content_for as well ... which makes some sense to me, but ... huh, just not getting it. Any helpful pointers appreciated.
Have you tried render_to_string in your controller when you're creating the record? That may allow you to just go ahead and "snapshot" the page.
I'm trying to use activeadmin's batch_action so I can run actions on more than one record. However when trying to run my rails server I get the following error.
undefined method `batch_action' for #<ActiveAdmin::ResourceDSL:0xb11f980> (NoMethodError)
Here is the activeadmin resource code:
ActiveAdmin.register Product do
batch_action :destroy, false
filter :name
index do
selectable_column
column :name
default_actions
end
controller do
def current_company
#current_company
end
end
end
I'm not sure where I'm getting it wrong - I need to show a corresponding checkboxes against the records and then define a batch action. Where am I getting it wrong here?
Got the answer :) was a wrong entry in my gemfile.
https://github.com/gregbell/active_admin/issues/1302
This is long so I hope you'll bear with me...
I have a model called Update with two subclasses, MrUpdate and TriggeredUpdate. Using single-table inheritance, added type field as a string to Update.
In my view I'm checking which type it is to decide what to display. I assumed since type is a string, I should do
<% if #update.type == 'MrUpdate' %>
This failed, i.e., it evaluated to false when the update was an MrUpdate. I noticed that at this point, #update.type.type is Class. OK, whatever, thought I, so I changed it to:
<% if #update.type == MrUpdate %>
and it worked, i.e., the comparison evaluated to true when the update was an MrUdpate. Then I did it again lower down in my view and it failed again (i.e., it evaluated to false when the update was an MrUpdate.)
Turns out the culprit is a couple of <%= link_to ... %> calls I use and make into buttons with jQuery. If I put this code in my view:
<br>
<%= #update.type.type %><br>
<%= #update.type %><br>
<%= link_to 'New Note', new_note_path(:update_id => #update.id), :class => "ui-button" %>
<br>
<%= #update.type.type %><br>
<%= #update.type %><br>
What I see is:
Class
MrUpdate
(the New Note button)
String
MrUpdate
It's changing from a class to a string! So what the heck am I doing wrong or missing here? Why should a link_to do that? First I'm not clear why it's not a string in the first place, but then really confused as to why it would change...?!? Any help or explanation would be helpful. I can just code it one way at the top and another way at the bottom, but that way madness lies. I need to understand why this is happening.
I figured out what the issue is here. Thanks to fl00r for pointing the way.
Yes, type is a reserved in Ruby 1.8.7 which tells you the class of the object you call it from. But it's also true that it is the name of the field used in Rails to indicate single-table inheriance and to store the name of the class of each instance of the subclass.
So I naively tried to access the value of the type field using #update.type. But what this was doing at the top of the view was calling the type method of the Object class in Ruby. For whatever reason, after the link_to calls, it was then access the value of the type field of the updates table.
While trying to figure this out I called #update.type in the Rails console and saw this message: "warning: Object#type is deprecated; use Object#class". Finally it registered what I was doing. When I changed my calls to:
<% if #update.class == MrUpdate %>
everything works as expected. I never saw a call to determine the type in any of the pages I found via Google about STI. This despite the fact that they all recommended using only one controller, wherein sometimes you must need to determine the class of the instance you have.
So, dumb mistake--pilot error. But maybe this will help someone else who gets tripped up on this.