I have a form that looks like this -
<%= form_for #photo,:html=>{:multipart=>true} do |f| -%>
<div>
<%= f.file_field :photo %>
<%= f.submit "Upload", :disable_with => 'Uploading...' %>
</div>
<%= #photo.errors[:photo].each do |attr,msg| %>
<span class="form-error"><%= msg %></span>
<% end %>
<% end -%>
My model has the following line
validates_presence_of :photo, :message => "Choose a file to upload"
For some reason the error message is rendering outside of containing span. The rendered HTML looks like this -
<form ..some attributes..><some hidden divs and inputs />
<div class="field_with_errors"><input type="file" name="photo[photo]" id="photo_photo"></div>
<input type="submit" value="Upload" name="commit" id="photo_submit" data-disable-with="Uploading...">
<span class="form-error"></span>
Choose a file to upload
</form>
I'm very new to rails, but this seems odd to me.
Why is my message outside of it's container?
Thanks.
Shouldn't this NOT have an equal sign (you like my double negative there)?
<%= #photo.errors[:photo].each do |attr,msg| %>
/ \
|
|
In other words, it should be:
<% #photo.errors[:photo].each do |attr,msg| %>
I've made this typo about a hundred times, and have finally got out of the habit of doing it. I'll bet that is part of the issue.
Your form_for needs and equal sign, because it outputs HTML into your view. The loop itself does not, because it is just a loop.
Related
I have a simple RSS feed for a website I'm trying to build. I want to do a read more link for posts and limit the output to 300 characters. My code looks like this:
<p id="notice"><%= notice %></p>
<h1 class="reviews">What They're Saying About Us</h1>
<br />
<h1 class="post-title"><%= image_tag("icons8-rss-40.png") %>RSS Feed</h1>
<% #home_blogs.each do |p| %>
<div class="blog-posts">
<h3><%= p.name %></h3> | <%= p.created_at.to_date %>
<br />
<p id="blog_post_content">
<% if p.entry.length > 200 %>
<%= truncate(p.entry, length: 300).html_safe %>
<%= link_to "...read more", p %>
<% else %>
<%= p.entry.html_safe %>
</p>
<% end %>
<br />
<%= image_tag("if__hashtag_2559811.png")%>Tag Cloud
<div class="tag-cloud">
</div>
</div>
<% end %>
<span class="pagination"><%= will_paginate #home_blogs %></span>
<br>
For whatever reason the html tags are included when I create a post even though I'm doing html_safe. Any ideas? Thanks
truncate automatically marks the output as html_safe and also escapes the content by default. This means your link is probably being escaped before you even get a chance to mark it as html_safe yourself.
You can pass an escape: false option to truncate in order to get it to skip the escaping that it does by default.
E.g.
<%= truncate(p.entry, length: 300, escape: false) %>
From the docs for truncate
The result is marked as HTML-safe, but it is escaped by default, unless :escape is false. Care should be taken if text contains HTML tags or entities, because truncation may produce invalid HTML (such as unbalanced or incomplete tags).
I want to render a collection of characters inside a form_for (so I can message multiple characters at once using check_box_tag inside each character_item). I'm using the following code but it is faulty. Only the first character is rendered inside the form, the rest appear outside the form. What am I doing wrong?
<%= form_for(:message, url: :messages, method: :post, html: { id: "message_form" }
) do |f| %>
<% if characters.any? %>
<% characters.each do |character| %>
<%= render "characters/character", character: character, f: f %>
<% end %>
<% end %>
<% end %>
This produces the following html:
<form id="message_form" enctype="multipart/form-data" action="/messages" accept-charset="UTF-8" method="post">
<div class="character_item" id="character_alfred">
</form>
<div class="character_item" id="character_barney">
<div class="character_item" id="character_chas">
<div class="character_item" id="character_dean">
EDIT
I've narrowed the problem down to this block of code. The layout is fine when I remove this:
<%= button_to destroy_relationship_path(
params: {
following_callsign: #character.callsign,
followed_callsign: followedcallsign,
viewed_callsign: viewedcallsign
}
),
class: 'btn btn-default btn-xs post_button',
id: 'unfollow-eye',
remote: true,
method: :delete do %>
<span class="glyphicon glyphicon-sunglasses" aria-hidden="true"></span>
<% end %>
Can anyone see what's wrong with it? I suspect there isn't anything wrong with the button code, I think it's something to do with having a button inside a form. I don't know. I am, as usual, baffled.
Turns out you can't put a button inside a form, because it closes the form. See this answer:
https://stackoverflow.com/a/34644553/346613
The solution is to convert all the button_to into link_to.
I have this line in controller/new for multiple records form:
#students = Array.new(quantity) {#stream.students.build}
View file:
<%= #errors.inspect %>
<%= form_for :students_list, {:url => create_students_list_stream_url(#stream) } do |students_list_form| %>
<% i=0 %>
<% #students.each do |student| %>
<% i=i+1 %>
<%= students_list_form.fields_for student do |student_form|%>
<%= render :partial => "students/add_students_to_stream", locals: {:student=>student, :student_form=>student_form, :i=>i} %>
<% end %>
<% end %>
<%= students_list_form.submit "Добавить студентов" %>
<% end %>
This generates looking rather right HTML, for one input:
<input id="name-field-1" type="text" name="students_list[student][account_attributes][name]" />
...
Note that it can be multiple objects per page, such as this input, as I want to create list of records.
But, as I can see from my server logs, params, which Rails gets, include only last record.
For example, I have forms for two 'students' on page.
<input id="name-field-1" type="text" name="student[student][account_attributes][name]" />
<input id="name-field-2" type="text" name="student[student][account_attributes][name]" />
And input there names John and Peter, my server logs will show:
"students_list"=>{"student"=>{"account_attributes"=>{"name"=>"Peter"}}}
and thats it.
In that case you must be adding multiple="multiple" and make name type as array.
html.
<input id="name-field-1" type="text" multiple="multiple" name="student[student][account_attributes][name][]" />
rails.
<%= form.text_field :object, id: "id", multiple: true %>
So that would return all the elements as Array for a same field name.
Fields are named exactly the same and do not have array sign in name, that's why browser overwrites them.
To make browser post array - fields should end up named students_list[][student][account_attributes][name] (note the additional [], by placing it in different parts of name you can control which elements are grouped)
So try fields_for 'students_list[]', ...
I am working in rails 2, I have a form containing data of two models, In one model I am validating fields and entering error using self.errors.add_to_base , but this is not displaying error on form and submitting that request successfully.
This is my Model validation\
validate :checkPunchingEntries
def checkPunchingEntries
if self.punch_in_time.blank? && self.punch_out_time.blank?
self.errors.add_to_base("Both 'Punch in' and 'Punch out' time can not be blank")
end
end
This is my Form
<% form_tag '/punching_requests/create', :method => :post, :class=>"punching_request_form" do %>
<% #punching_request.errors.full_messages.each do |msg| %>
<p class="error"><%=msg%></p>
<% end %>
<p>
<label>Date </label>
<%= text_field_tag 'date'%> <%= calendar_for("date") %>
</p>
<p>
<label> </label>
<input type="checkbox" onclick="punch_in_toggle()">Punch In</input>
<input type="checkbox" onclick="punch_out_toggle()">Punch Out</input>
</p>
<div id="punch_in">
<p>
<label>Punch In Time </label>
<%= text_field_tag 'punch_in_time'%>
</p>
</div>
<div id="punch_out">
<p>
<label>Punch Out Time </label>
<%= text_field_tag 'punch_out_time'%>
</p>
</div>
<p>
<label>Assign To</label>
<%= select_tag(:approved_by, options_from_collection_for_select(#human_resource_persons, "id", "login")) %>
</p>
<p>
<label>Reason </label>
<%=text_area_tag 'reason'%>
</p>
<p class="actions"><label></label><%= submit_tag 'Save' %></p>
<% end %>
It comes into validation, but error is not shown on validation fails.
Have you tried the IRB console? If not, take a look what is going on there, just to be sure, that #punching_request.errors contains something.
try this
def checkPunchingEntries
if self.punch_in_time.blank? && self.punch_out_time.blank?
errors[:base]<< "Both 'Punch in' and 'Punch out' time can not be blank"
end
end
and use form_for and #punching_request
for example
# in your controller
def new
#punching_request = PunchingRequest.new
end
def create
...
...
end
your form look like in your new.html.erb
form_for(#punching_request)
...
...
end
In this you're generating the form using form_tag and the errors you're expecting would be stored in the form builder,form_for.
Instead of form_tag use form_for(#punching_request). This should do the trick.
How would one go about turning the following code into the latter?
<div id="faqs">
<% if #faqs.length > 0 %>
<% #faqs.each do |faq| %>
<div class="faq">
<strong>Q:</strong> <%= faq.question %>
<br />
<strong>A:</strong> <%= faq.answer %>
</div>
<% end %>
<% else %>
<p>No FAQs to display.</p>
<% end %>
</div>
<div id="faqs">
<% #faqs.empty? ? content_tag(:p, "No FAQs to display.") : #faqs.each do |faq| %>
<div class="faq">
<strong>Q:</strong> <%= faq.question %>
<br />
<strong>A:</strong> <%= faq.answer %>
</div>
<% end %>
</div>
I'm curious as to whether I can get the latter code to work. The only element of it that is failing at the moment is that the content_tag() is not displaying - this is due to the fact that I'm not using printable ruby tags (<%= # %>) but using them will dump out the FAQ objects underneath the content.
I considered the use of puts() to print the content_tag() while inside the ruby tags but that didn't work.
I've tried to search for this issue but haven't yielded anything useful.
Is this achievable and if so, does it have any benefits other than being prettier?
One way to make the later code to work if you can put the body of the loop in a helper function and return the out put of content_tag from that. The line in view file might be somewhat like this.
<%= #faqs.empty? ? content_tag(:p, "No FAQs to display.") : printList(#faqs) %>
and your printList function will return the output of nested content_tags. You can make a generic list printing function which can be used for any list.
Something so obvious but still shared.
This should work (for clarity, I moved FAQ tag generation in separate helper method):
<div id="faqs">
<%= raw (#faqs.empty? ? content_tag(:p, "No FAQs to display.") : #faqs.map { |faq| faq_div(faq) }.join) %>
</div>
or, perhaps more clean:
<div id="faqs">
<%= content_tag(:p, "No FAQs to display.") if #faqs.empty? %>
<%= raw #faqs.map { |faq| faq_div(faq) }.join %>
</div>
meanwhile, in helpers:
def faq_div(faq)
'<div class="faq"><strong>Q:</strong> %s<br /><strong>A:</strong> %s</div>' % [faq.question, faq.answer]
end
This should work:
<% if #faqs.each do |faq| %>
<div class="faq">
<strong>Q:</strong> <%= faq.question %>
<br />
<strong>A:</strong> <%= faq.answer %>
</div>
<% end.empty? %>
<p>No FAQs to display.</p>
<% end %>