问题
I have a simple question, all I need is to edit and delete one to many relationship in rails in my case Status belongs to user and User has many statuses
Here is what I have tried
In status
edit.html.erb
<h1>Edit Status of doctor <%= @user.name %></h1>
<%= form_for @status,:url => {:action => :update, :id => @user.id} do |f| %>
status: (Received, Processed, Shipped) <%= f.text_field :name %><br>
<%= f.submit %>
<% end %>
I have this error undefined method `name' for nil:NilClass
status controller
class StatusesController < ApplicationController
def new
@user =User.find(params[:id])
@status = @user.statuses.build
end
def create
@user =User.find(params[:id])
@status = @user.statuses.build(status_params)
if @status.save
redirect_to new_status_path(:id => @user.id)
end
end
def edit
end
def update
@user =User.find(params[:id])
if @user.statuses.update(status_params)
redirect_to root_path, notice: "user Information updated successfully"
else
flash.now[:error] = "Couldn't update!"
render :edit
end
end
private
def status_params
params.require(:status).permit(:name)
end
end
In the user show.html.erb
<%= link_to @user.name.capitalize, :controller => :statuses, :action => :new, :id => @user.id %><br>
<% if !@user.statuses.blank? %>
<% for item in @user.statuses %>
<strong>Status:</strong> <%= item.name %>
<%= link_to "Edit", edit_status_path(item),class: "btn btn-success" %><br>
<% end %>
<% else %>
No status yet
<% end %>
user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :statuses
end
status.rb
class Status < ActiveRecord::Base
belongs_to :user
end
回答1:
You’re not setting an varible @user in your controller, use the before action to keep your DRY principle.
class StatusesController < ApplicationController
before_action :set_user
def new
@status = @user.statuses.build
end
def create
@status = @user.statuses.build(status_params)
if @status.save
redirect_to new_status_path(:id => @user.id)
end
end
def edit
end
def update
if @user.statuses.update(status_params)
redirect_to root_path, notice: "user Information updated successfully"
else
flash.now[:error] = "Couldn't update!"
render :edit
end
end
private
def set_user
@user = User.find(params[:id])
end
def status_params
params.require(:status).permit(:name)
end
end
to delete all associated records of this user, put in your file user.rb
has_many :statuses, dependent: :destroy
回答2:
I solve it by doing this
class StatusesController < ApplicationController
before_action :authenticate_user!,except: [:index,:show]
before_action :find_status ,only:[:show,:update,:edit,:destroy]
def new
@user =User.find(params[:id])
@status = @user.statuses.build
end
def create
@user =User.find(params[:id])
@status = @user.statuses.build(status_params)
if @status.save
redirect_to doctor_path(:id => @user.id)
end
end
def edit
end
def update
if @status.update(status_params)
redirect_to root_path, alert: "user Information updated successfully"
else
flash.now[:error] = "Couldn't update!"
render :edit
end
end
def destroy
@status.destroy
redirect_to doctors_path, notice: "Status deleted Successfully"
end
private
def find_status
@status = Status.find(params[:id])
end
def status_params
params.require(:status).permit(:name)
end
end
In status edit file
<%= form_for @status do |f| %>
status: (Received, Processed, Shipped) <%= f.text_field :name %><br>
<%= f.submit %>
<% end %>
In user index show
<% if !@user.statuses.blank? %>
<% for item in @user.statuses %>
<strong>Status:</strong> <%= item.name %>
<% if current_user && current_user.admin? %>
<%= link_to "Edit", edit_status_path(item),class: "btn btn-success" %>
<%= link_to "Delete", item, method: :delete, data: {confirm: "Are you sure?"},class: "btn btn-danger" %><br>
<% end %>
<% end %>
<% else %>
No status yet
<% end %>
来源:https://stackoverflow.com/questions/62719448/how-to-update-and-edit-one-to-many-relationship-mvc-in-ruby-on-rails