0

I am sitting here since the Dawn of Times trying to toggle a boolean in Rails for an admin to validate submissions.

I have a standard "Article" model, which has_many "Prosols" (which in turn belongs_to "Article"). A Prosol has a boolean "profeat1". I am trying to toggle it thanks to a set of button_to (as follows). I am looping through the articles prosols, showing them in a bootstrap template, and showing for each a button to validate or not. The issue is that all buttons point to the first prosol. It seems that the prosol ID is not accurately passed to the controller.

No route matches {:action=>"unpro1", :article_id=>5, :controller=>"prosols", :id=>nil} missing required keys: [:id]

Here is the code.

article#show.html.erb - Adding lines from original Code

<% if admin_signed_in? %>

<% @article.prosols.in_groups_of(2) do |group| %>
 <div class="container-fluid">
  <% group.compact.each do |prosol| %>

  <div class="col-md-6">
  <div class="box3">
  <h4><%= prosol.title %></h4> <br>
  <%= prosol.body %> <br>

  <% if prosol.profeat1 == false %>
    <%= button_to "Do it", pro1_article_prosol_path(:article_id => @article.id, :id => @prosol.id), :class => 'btn btn-info'%>

  <% else %>
    <%= button_to "Undo it", unpro1_article_prosol_path(:article_id => @article.id, :id => @prosol.id), :class => 'btn btn-info'%>

  <% end %>
</div>
</div>
<% end %>
</div>
<% end %>
<% end %>

prosols_controller.rb

def pro1
  @article = Article.find(params[:article_id])
  @prosol = @article.prosols.find(params[:id])
  @prosol.update(profeat1: true)
  redirect_to article_path(@article)
end

def unpro1
  @article = Article.find(params[:article_id])
  @prosol = @article.prosols.find(params[:id])    
  @prosol.update(profeat1: false)
  redirect_to article_path(@article)
end

routes.rb

resources :articles do
  resources :prosols do
    post 'pro1', on: :member
    post 'unpro1', on: :member
  end
end

Right now I think the issue is with passing the nested resource (prosol) ID to controller. If you see a better/different way of achieving the end result, I will warmly welcome your advice. Again, my goal is to display all prosols for an article, with an admin button to validate or not. I have thoroughly tried everything else on StackO so far but to no avail.

Awaiting the Savior... Thanks in advance.

EDIT : THIS IS THE SOLUTION - article#show.html.erb

<% if prosol.profeat1 == false %>
  <%= button_to "Do it", pro1_article_prosol_path(:article_id => @article.id, :id => prosol.id), :class => 'btn btn-info'%>

<% else %>
  <%= button_to "Undo it", unpro1_article_prosol_path(:article_id => @article.id, :id => prosol.id), :class => 'btn btn-info'%>

<% end %>

My initial error had 2 sources: - pointing to the nested prosol with an @ instead of no pointer, as it was already pointed to in the loop - and bad leftovers in the Articles controller, as follows:

def show
 @article = Article.find(params[:id])
 @prosols = @article.prosols.all    <--- wrong
 @prosol = @article.prosols.build   <--- wrong
end

Great. Now it's beer o'clock.

Jando
  • 3
  • 4
  • Where are you setting @prosol for the link itself? – SomeDudeSomewhere Apr 16 '15 at 23:31
  • Good point. The code in the "show" view above is embedded into a loop: <% @article.prosols.in_groups_of(2) do |group| %>
    <% group.compact.each do |prosol| %>
    – Jando Apr 16 '15 at 23:33
  • can you update your question with the View code and the Action from the controller that sets those params? – SomeDudeSomewhere Apr 16 '15 at 23:49
  • `<% if prosol.profeat1 == false %>` shouldnt there be an @? – forthowin Apr 17 '15 at 01:15
  • @DevDude thanks for your feedback. I updated the code. But which controller Action do you mean for setting the params ? :id should be set at creation, and the methods pro1 and unpro1 are supposed to find the ids ? – Jando Apr 17 '15 at 09:43
  • @forthowin thanks for your feedback but that did not change. I am often confused about when to use/not use an @ but this time it is fine. – Jando Apr 17 '15 at 09:45
  • add a `binding.pry` before `<% if prosol.profeat1 == false %>`, what do you see? – forthowin Apr 17 '15 at 16:25
  • I never heard about Pry before, will definitely give it a pry, thanks for the tip. My error stemmed from a leftover in the Articles controller. – Jando Apr 17 '15 at 22:16

2 Answers2

2

Shouldn't this:

<% if prosol.profeat1 == false %>
  <%= button_to "Do it", pro1_article_prosol_path(:article_id => @article.id, prosol.id => prosol.id), :class => 'btn btn-info'%>

<% else %>
  <%= button_to "Undo it", unpro1_article_prosol_path(:article_id => @article.id, prosol.id => prosol.id), :class => 'btn btn-info'%>

<% end %>

look like this?

<% if prosol.profeat1 == false %>
  <%= button_to "Do it", pro1_article_prosol_path(:article_id => @article.id, :id => prosol.id), :class => 'btn btn-info'%>

<% else %>
  <%= button_to "Undo it", unpro1_article_prosol_path(:article_id => @article.id, :id => prosol.id), :class => 'btn btn-info'%>

<% end %>

Or even better:

<% if prosol.profeat1 == false %>
  <%= button_to "Do it", pro1_article_prosol_path(@article, prosol), :class => 'btn btn-info'%>

<% else %>
  <%= button_to "Undo it", unpro1_article_prosol_path(@article, prosol), :class => 'btn btn-info'%>

<% end %>
  • Oh yes it should. But when trying this, Rails is not in the mood and is telling me that "No route matches {:action=>"pro1", :article_id=>"5", :controller=>"prosols", :id=>nil} missing required keys: [:id] but thanks anyway – Jando Apr 17 '15 at 13:29
  • Ok this code totally works. Awesome. My error stemmed from leftovers in the Article controller. I'll edit the question. – Jando Apr 17 '15 at 22:17
0

The issue appears to be that you are using @prosol in your button, which has not been assigned and is therefore returning nil.

Your loop defined in your comment, sets prosol, which is not @prosol. Drop the '@' symbol and you should be fine.

-- edit--

As in id => prosol.id ...

  <% if prosol.profeat1 == false %>
    <%= button_to "Do it", ..., :id => prosol.id), :class => 'btn btn-info'%>

  <% else %>
    <%= button_to "Undo it", ..., :id => prosol.id), :class => 'btn btn-info'%>

  <% end %>

Your error is showing id => nil because @prosil is a nil object.

Matt Stevens
  • 1,104
  • 1
  • 12
  • 24
  • Thanks for your input. I tried some relevant changes as in the edit above. :id in itself is not recognized, but prosol.id is. Now the issue is that all buttons toggle the first one, which mean they only point to the first prosol.id they find, I believe... I am not sure how to get out of this. – Jando Apr 17 '15 at 09:45
  • Just made my answer more explicit, – Matt Stevens Apr 17 '15 at 19:56
  • I follow your logic and theoretically concur with it; but when trying this exact bit of code, I still get: No route matches {:action=>"pro1", :article_id=>5, :class=>"btn btn-info", :controller=>"prosols", :id=>nil} missing required keys: [:id] – Jando Apr 17 '15 at 22:07
  • Well I just found the issue. It was some leftovers in the Articles controller. I'll edit my initial question. Your code works. Awesome. – Jando Apr 17 '15 at 22:15