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.