Hiltsje
Hiltsje

Reputation: 79

How to hide form when there is one instance of the associated model #rails #beginner

I'm trying to create a comment like system where the user can add a 'outcome' to a 'decision'. I like to hide the outcome create form to 'hide' when there is 1 added to the decision.

My best guess to accomplish this, is to count the number of associates instances of outcomes to decisions and create a if statement for hiding the form when there is more than 0 instances of outcome.

I tried different ways of accomplishing this but i can't seem to make the counting or if statement to work. I am new to coding for your reference :-).

Can anyone give me a suggestion on how to tackle this?

My code: controllers/decisions_controller.rb

class DecisionsController < ApplicationController
before_action :find_decision, only: [:show, :edit, :update, :destroy]

  def index
# gets all rows from decision table and puts it in @decision variable
    @decisions = Decision.all
  end

  def show
# find only the decision entry that has the id defined in params[:id]
  end
# shows the form for creating a entry
  def new
    @decision = Decision.new
  end
# creates the entry
  def create
    @decision = Decision.new(decision_params)
      if @decision.save
        redirect_to @decision
      else
        render 'new'
      end
  end
# shows the form for editing a entry
  def edit
  end
# updates the entry
  def update
    if @decision.update(decision_params)
      redirect_to @decision
    else
      render 'edit'
    end
  end

  def destroy
    @decision.destroy
    redirect_to root_path
  end

  private
  def find_decision
# Loads the right entry.
      @decision = Decision.find(params["id"])
  end

  def decision_params
    params.require(:decision).permit(:title, :forecast, :review_date)
  end

end

controllers/outcomes_controller.rb

class OutcomesController < ApplicationController
    def create
        @decision = Decision.find(params[:decision_id])
        @outcome = @decision.outcomes.create(params[:outcome].permit(:actual, :strength, :weakness))
          redirect_to decision_path(@decision)
    end
end

models/outcome.rb

class Outcome < ActiveRecord::Base
  belongs_to :decision
end

models/decision.rb

class Decision < ActiveRecord::Base
  has_many :outcomes
end

decisions/show.html.erb

    <h1>Decision showpage</h1>

<h2><%= @decision.title %></h2>
<p><%= @decision.created_at %></p>
<p><%= @decision.forecast %></p>
<p><%= @decision.review_date %></p>

<%= render @decision.outcomes %>


<%= link_to "Delete Decision", decision_path(@decision), method: :delete, data: { confirm: "Are you sure?" } %>

<%= render "outcomes/form" %>
<%= render "outcomes/outcome" %>

outcomes/_form.html.erb

<%= form_for([@decision, @decision.outcomes.build]) do |f| %>
  <%= f.label :actual %>:
  <%= f.text_field :actual %> <br/>

  <%= f.label :strength %>:
  <%= f.text_area :strength %> <br/>

  <%= f.label :weakness %>:
  <%= f.text_area :weakness %> <br/>
  <%= f.submit %>
  <% end %>

outcomes/_outcome.html.erb

<h2>outcome</h2>
<%= @decision.outcomes.first.actual %> </br>
<h3>What i found i'm good at</h3>
<%= @decision.outcomes.first.strength %> </br>
<h3>What i found i'm weak at</h3>
<%= @decision.outcomes.first.weakness %>

Upvotes: 2

Views: 70

Answers (2)

Richard Peck
Richard Peck

Reputation: 76774

Sounds like standard conditional logic:

#app/views/decisions/show.html.erb
<h1>Decision</h1>

<h2><%= @decision.title %></h2>
<% %w(created_at forecast review_date).each do |option| %>
    <%= content_tag :p, @decision.send(option) %>
<% end %>

<% if @decision.outcomes.any? %>
   <%= render @decision.outcomes %>
   <%= render "outcomes/form" %>
<% end %>

<%= link_to "Delete Decision", decision_path(@decision), method: :delete, data: { confirm: "Are you sure?" } %>

My best guess to accomplish this, is to count the number of associates instances of outcomes to decisions and create an if statement for hiding the form when there is more than 0 instances of outcome.

Sure - it's called conditional logic

In your case, you're looking for several potential methods (to determine the size of the associated data):

  • length (Pardeep's answer) -- queries the array's length
  • size -- either invokes count (SQL query) or length
  • count -- performs db query (should only be used if no data loaded)
  • any? -- very similar to length except returns true/false depending on whether any items exist

Good ref here: ActiveRecord: size vs count

  • if you already load all entries, say User.all, then you should use length to avoid another db query

  • if you haven't anything loaded, use count to make a count query on your db

  • if you don't want to bother with these considerations, use size which will adapt

I used .any? because it's the most succinct in this instance.

Upvotes: 0

Pardeep Saini
Pardeep Saini

Reputation: 2102

<h1>Decision showpage</h1>
<h2><%= @decision.title %></h2>
<p><%= @decision.created_at %></p>
<p><%= @decision.forecast %></p>
<p><%= @decision.review_date %></p>

<%= render @decision.outcomes %>


<%= link_to "Delete Decision", decision_path(@decision), method: :delete, data: { confirm: "Are you sure?" } %>
<%if @decision.outcomes.length < 1 %>
    <%= render "outcomes/form" %>
<%end%>
<%= render "outcomes/outcome" %>

Upvotes: 1

Related Questions