Marty
Marty

Reputation: 2224

Nil value: no issue when visiting edit view but causing error when fired 'render edit'

User has a many-to-many relationship with Organization through Relationship. The User table contains a default_relationship_id, which can also be nil.

In the edit view with the user's profile there's a dropdown box from which the user can select a relationship as default. All of this works.

Now consider the following specific scenario: user has no value for default_relationship_id and visits his edit page. If it then submits valid data, it works. However, if user submits invalid data and then render edit gets fired from the controller. This produces an error undefined method 'empty?' for nil:NilClass referring to the dropdown box. This error is not there if default_relationship_id its value wasn't nil in the first place.

Why does render edit fail because of this nil value, while is it possible to visit the edit view? And how to deal with this?


Migration:

t.integer  :default_relationship_id

Only model validation for default_relationship_id applies to when it is not nil.

Code in the view:

<label class="col-md-4 control-label" for="default_relationship_id">Default</label> 
<div class="col-md-8">
  <%= f.collection_select :default_relationship_id, @relationships, :id, :name, {}, {class: 'form-control input-md'} %>
</div>

Controller method:

def edit
  @user = User.find(params[:id])
  @relationships = @user.relationships.where('member = ?', true)
end

def update
  @user = User.find(params[:id])
  if @user.update_attributes(strong_params)
    flash[:success] = "Updated"
    redirect_to @user
  else
    render 'edit'
  end
end

Upvotes: 2

Views: 64

Answers (1)

user4776684
user4776684

Reputation:

You have to initialize @relationships variable in the else branch:

 def update
  @user = User.find(params[:id])
  if @user.update_attributes(strong_params)
    flash[:success] = "Updated"
    redirect_to @user
  else
    @relationships = @user.relationships.where(member: true)
    render 'edit'
  end
end

Or to avoid duplication you can leave your action along and adjust your view instead:

 <div class="col-md-8">
   <%= f.collection_select :default_relationship_id, @user.relationships.where(member: true), :id, :name, {}, {class: 'form-control input-md'} %>
 </div>

In this case you can also remove "@relationships = @user.relationships.where('member = ?', true)" from your edit and probably show method.

Upvotes: 3

Related Questions