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.
Related
Would anyone be able to tell me why this text is showing up out of the blue on my Rails 7 app. I have poured over the scss, js, and html unable to find what is rendering it. Additionally the app contains another object (called employee and not template) and used exactly the same in the source code but does have this plain text added to it.
The only difference between them is that I am using this object in a modal vs no modal but both are using turbo frames. I would be happy to post some code but I thought someone might easily recognize it first.
Here is the partial.
<%= #templates.each do |temp| %>
<div class="template__actions">
<div class="line-item__name">
<%= temp.name %>
</div>
<%= link_to "<i class='bi bi-trash'
style='font-size: 1.5rem; color:
red;'></i>".html_safe,
[temp],
data: {"turbo-method": :delete},
form: { data: {turbo_frame: "_top" } },
class:"btn btn--light staff_icon" %>
<%= link_to "<i class='bi bi-pencil-square'
style='font-size: 1.5rem; color:
black;'></i>".html_safe,
[:edit, temp],
class:"btn btn--light staff_icon" %>
</div>
<% end %>
This is your problem:
<%= #templates.each do |temp| %>
The equal sign makes it print the template array.
Change it to:
<% #templates.each do |temp| %>`
You are printing the loop in your erb syntax.
<%= is to print the return and you are implicitly returning the collection at the end of the loop.
Instead just use <% to declare the erb and not print the return.
change line 1
<%= #templates.each do |temp| %>
to
<% #templates.each do |temp| %>
I have Challenges containing Puns, and it is possible to vote on puns. On the Challenge Show page, all puns are rendered and show their votes count. This is currently on the view page:
<%= render #challenge.puns.reverse %>
<br>
<div id="form">
<%= render "puns/form" %>
</div>
I want the puns form to appear above the items (puns) already submitted. But if swap them around, like this:
<div id="form">
<%= render "puns/form" %>
</div>
<%= render #challenge.puns.reverse %>
I get a controller error and pun.id is not suddenly not available and the voting link breaks.
No route matches {:action=>"upvote", :challenge_id=>"9", :controller=>"puns", :id=>nil}, missing required keys: [:id]
Here is the puns/form part that is causing the issue
<% if signed_in? %>
<% if current_user.voted_for? pun %>
<%= pun.votes_for.size %>
<span class="pun_text"><%= link_to pun.pun_text, challenge_pun_path(#challenge, pun.id) %></span>
<% else %>
<%= link_to like_challenge_pun_path(#challenge, pun.id), method: :put do %>
<span class="heart_like">❤</span> <%= pun.votes_for.size %>
<% end %>
<span class="pun_text"><%= link_to pun.pun_text, challenge_pun_path(#challenge, pun.id) %></span>
<% end %>
<% end %>
It is the like_challenge_pun_path that throws an error but I cannot understand why. I am declaring #challenge again here, so it should be able to get the id.
Here is the form for the puns:
<%= form_for([#challenge, #challenge.puns.build]) do |f| %>
<span class=".emoji-picker-container">
<%= f.text_area :pun_text, placeholder: "Add pun", data: { emojiable: true } %>
</span>
<%= f.submit %>
<% end %>
Also, here is my routes setup
resources :challenges do
resources :puns do
member do
put "like", to: "puns#upvote"
put "dislike", to: "puns#downvote"
end
end
end
and the corresponding action to upvote
def upvote
#pun = #challenge.puns.find(params[:id])
#pun.upvote_by current_user
redirect_to #challenge
end
Can anyone help?
I think the code is for the puns collection.
I assume the issue is that in the form you have something like:
#challenge.puns.build
So in #challenge.puns collection appears not persisted record (without id), so path for this model cannot be generated.
As a quick solution I suggest:
<%= render #challenge.puns.reverse.select(&:persisted?) %>
UPDATE:
As I assumed you have
<%= form_for([#challenge, #challenge.puns.build]) do |f| %>
You can also try:
<%= form_for([#challenge, Pun.new]) do |f| %>
Or solve it in the controller. But need to see controller code for it.
Im submitting my form with checkboxes via Jquery with remote true but its not working. Its keeps rendering the html format in the controller and i can work out why.
Here is my submit button and form:
<%= button_to "Read sel", root_path, class: "btn btn-info btn-sm padlr", id: "notification-submit" %>
<%= form_tag read_selected_notifications_path, :authenticity_token => true, remote: true ,id: "notification-form" do %>
<% #notifications.each do |x| %>
<div class="notification-body flerowspb">
<div class="flerowspb" style="width:80%">
<div class="notif-check flecolcen">
<%= check_box_tag "read_notif[]", value="#{x.id}" %>
</div>
<div class="notif-details ">
<div class="notif-time flerowspb">
<% if !x.viewed %>
<span class="glow"> New <%= x.notification_type.capitalize %></span>
<% else %>
<span><span class="text-grey"> New <%= x.notification_type.capitalize %></span></span>
<% end %>
<span class="text-grey font-small"> <%= time_ago_in_words(x.created_at) %> ago</span>
</div>
<div class="notif-body font-medium text-grey">
<span class="text-blue"><%= link_to x.sender.username, profile_path(x.sender) %> </span> <%= x.title %> <br>
Click <span class="text-blue"><%= link_to "Here", entry_path(x.entry_id, notification_id: x.id) %> </span> to view it
</div>
</div>
</div>
<div class="notif-image">
<%= image_tag x.entry.image.small_thumb %>
</div>
</div>
<% end %>
<% end %>
So there is no actual submit button for the form as i want the button above the form not below it like this,
I understand i have to add :authenticity_token => true as rails doesnt add this to form_tag with remote: true
Here is my controller:
def read_selected
Notification.read_selected(current_user.id, params[:read_notif])
respond_to do |format|
format.html{
flash[:success] = "Selected notifications marked as read"
redirect_to notifications_path
}
format.js{
render 'notifications/jserb/read_selected'
}
end
end
Here is the js code:
$(document).on('turbolinks:load', function(){
if (window.location.href.match(/\/notifications/)) {
$('#notification-submit').on('click', function(e){
console.log('oisdjfilds');
e.preventDefault();
$('#notification-form').submit();
});
}
});
EDIT: I added in a submit button at the bottom of the form and it works as it should do, So it something to do with the way i'm submitting the form
I assume you're using Rails 5, since there is such an inconsistency in its behavior. Please, check out the issue
As far as I understand the quick solution for your problem is going to be:
Get the form HTML element:
form = document.getElementById('notification-form');
or
form = $('#notification-form')[0]
And then fire Rails submit:
Rails.fire(form, 'submit');
or
form.dispatchEvent(new Event('submit', {bubbles: true}));
I am having a weird issue where my rails application seemingly isn't reading the local variable passed to the partial, but only inside of form_for.
I have a set up a button where a user can bookmark an object, let's call it zoo.
The code looks like this:
Zoo Listing View:
<li><%= render 'directory/bookmarks', zoo: zoo %></i></li>
Then the directory/bookmarks partial:
<% if user_signed_in? %>
<% if current_user.has_zoo_bookmarked_already? %>
<%= form_for(current_user.bookmarks.find_by_zoo_id(zoo.id), html: { method: :delete }, remote: true) do |f| %>
<%= button_tag do %>
<button class="btn btn-lg btn-block btn-primary">remove bookmark
<% end %>
<% end %>
<% else %>
<%= form_for(current_user.bookmarks.build(zoo_id: zoo.id)) do |f| %>
<%= f.hidden_field :zoo_id, value: zoo.id %>
<%= button_tag do %>
<button class="btn btn-lg btn-block btn-primary">bookmark
<% end %>
<% end %>
<% end %>
<% else %>
<% end %>
Anyway, the problem is the zoo.id on the 3rd line is not being evaluated. I get this error.
undefined method `model_name' for NilClass:Class
The weird part is that locals are being read on the page.
If I place this code snippet <%= zoo.id %> anywhere on the page, I get the id. Then, the find_by_zoo_id is being evaluated also...if I put 255 a hardcoded number, it works. Or if I set it to a variable, #id = 255 and then pass in the #id, it works.
The zoo.id only does not work inside of the form_for for some reason. If I set it to an instance variable on the page, #id = zoo.id, that doesn't work either.
Any ideas? I'm sure it is something minor.
EDITED:
The relationship is has_many :through. Forgot to mention, I use this code for a different association in the same application and it works fine.
That error you're getting suggests current_user.bookmarks.find_by_zoo_id(zoo.id) is nil. find_by_zoo_id might be returning you nothing
Of course it was -- I was iterating through a list of zoos with bookmarks, but not all of them would be bookmarked by the user. I just had to add an additional condition.
<% if user_signed_in? %>
<% if current_user.has_zoo_bookmarked_already? && current_user.bookmarks.find_by_zoo_id(zoo.id) %>
#....
How do I wrap a link around view code? I can't figure out how to pass multiple lines with ruby code to a single link_to method. The result I am looking for is that you click the column and get the show page:
<div class="subcolumns">
<div class="c25l">
<div class="subcl">
<%= image_tag album.photo.media.url(:thumb), :class => "image" rescue nil %>
</div>
</div>
<div class="c75r">
<div class="subcr">
<p><%= album.created_at %></p>
<%= link_to h(album.title), album %>
<p><%= album.created_at %></p>
<p><%= album.photo_count %></p>
</div>
</div>
</div>
link_to takes a block of code ( >= Rails 2.2) which it will use as the body of the tag.
So, you do
<%= link_to(#album) do %>
html-code-here
<% end %>
But I'm quite sure that to nest a div inside a a tag is not valid HTML.
EDIT: Added = character per Amin Ariana's comment below.
Also, this may be an issue for some:
Make sure to write <%= if you are doing a simple link with code in it instead of <%.
e.g.
<%= link_to 'some_controller_name/some_get_request' do %>
Hello World
<% end %>
For older Rails versions, you can use
<% content_tag(:a, :href => foo_path) do %>
<span>Foo</span>
<% end %>
You can use link_to with a block:
<% link_to(#album) do %>
<!-- insert html etc here -->
<% end %>
A bit of a lag on this reply I know -- but I was directed here today, and didn't find a good answer. The following should work:
<% link_to raw(html here), #album %>