Kevin Kevin - 2 months ago 12
Ruby Question

Rails 4 fields_for not displaying or updating

I have a nested relationship where dashboard has many rewards, and I am trying to add a fields_for to the page in order to edit the rewards. Unfortunately, it doesn't seem to be working and I don't know why.

Here's what I have.

Dashboard model:

class Dashboard < ActiveRecord::Base
belongs_to :manager

has_many :rewards
accepts_nested_attributes_for :rewards, allow_destroy: true
end


Rewards model:

class Reward < ActiveRecord::Base
belongs_to :dashboard
end


Dashboard controller:

class DashboardsController < ApplicationController
before_action :authenticate_manager!

# Requires user to be signed in
def index
@dashboards = Dashboard.all
end

def new
@dashboard = Dashboard.new
end

def edit
@dashboard = Dashboard.find(params[:id])
end

def create
@dashboard = Dashboard.new(dashboard_params)
@dashboard.save

if @dashboard.save
redirect_to dashboard_path(@dashboard)
else
render :action => new
end
end

def update
@dashboard = Dashboard.find(params[:id])

if @dashboard.update(dashboard_params)
redirect_to :action => :show
else
render 'edit'
end
end

def show
@dashboard = Dashboard.find(params[:id])
end

def destroy
@dashboard = Dashboard.find_by_id(params[:id])

if @dashboard.destroy
redirect_to dashboards_path
end
end

private
def dashboard_params
args = params.require(:dashboard).permit(:title, :description, :rewards, {rewards_attributes: [ :id, :title, :referralAmount, :dashboardid, :selected, :_destroy] } )
args
end

end


Form in dashboards view:

<%= form_for :dashboard, url: dashboard_path(@dashboard), method: :patch do |f| %>
<% if @dashboard.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(@dashboard.errors.count, "error") %> prohibited
this dashboard from being saved:
</h2>
<ul>
<% @dashboard.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :description %><br>
<%= f.text_field :description %>
</p>

<%= f.fields_for :rewards do |reward| %>

<%= reward.label :title %><br>
<%= reward.text_field :title %>
<%= reward.check_box :_destroy %>
<%= reward.label :_destroy, "Remove reward" %>

<% end %>

<p>
<%= f.submit %>
</p>
<% end %>


I went ahead and manually added rewards to the database through the rails console and it worked beautifully, but they are not showing up on the page. They will show up if I iterate through them like so

<% if @dashboard.rewards.any? %>
<ul>
<% @dashboard.rewards.each do |reward| %>
<li><%= reward.title %></li>
<li><%= reward.referralAmount %></li>
<% end %>
</ul>
<% else %>
<p>no rewards</p>
<% end %>


However the fields_for does not display the rewards or their content and resultingly allow one to edit them.

Let me know if you need further information/code.

Answer

Try to modify your:

View:

  <% if @dashboard.errors.any? %>
    <div id="error_explanation">
      <h2>
        <%= pluralize(@dashboard.errors.count, "error") %> prohibited
        this dashboard from being saved:
      </h2>
      <ul>
        <% @dashboard.errors.full_messages.each do |msg| %>
          <li><%= msg %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <%= form_for @dashboard, url: dashboard_path(@dashboard) do |f| %>
  ........
  <% end %>

Controller (has_many relationship):

def new
    @dashboard = Dashboard.new
    @dashboard.rewards.build
end

private 
def dashboard_params 
  params.require(:dashboard).permit(:title, :description,
    rewards_attributes: [ 
    :id,
    :title,
    :referralAmount,
    :dashboardid,
    :selected,
    :_destroy
  ])        
end

You don't have to set the method: patch if form. Once you got in edit page, Rails will use the update action in controller when form submission.

To check it, run rake routes, you will see somsthing like this:

PATCH  /dashboards/:id(.:format)                dashboards#update
PUT    /dashboards/:id(.:format)                dashboards#update
Comments