kong
kong

Reputation: 453

Rails: updating joined Active Model's attribute

I'm new to RoR. My question is about updating associated Active Model's attr.

class User
  has_many :toys
end

class Toy
  belongs_to :user
end

and I have a page with a form of user where I can update user's attributes, and also certain attributes of associated user_devices:

<%= f.text_field :age %> # from user
<%= f.text_field :email %> # from user
....
<%= f.check_box :is_new %> # from toy!!

When I post the form and update all the attributes using update_attributes(), it shows "ActiveModel::MassAssignmentSecurity::Error"

@user.update_attributes(params[:user]) # it gives ActiveModel::MassAssignmentSecurity::Error

Another problem is, I don't know how to name the "is_new" attribute as it's in toy table.. Should it be :toys_is_new?

I want the associated toy's attributes to be updated as well. Can you help me with this?

Upvotes: 2

Views: 60

Answers (2)

Tobias
Tobias

Reputation: 4653

You have to use Strong Parameters. It was introduced in Rails 4.

Example:

You have a model User with id, firstname, lastname, email. The user should only be able to update the first and lastname.

Your View:

<%= form_for @user do |f| %>
  <%= f.text_field :firstname %>
  <%= f.text_field :lastname %>
  <%= f.submit %>
<% end %>

Your Controller:

before_action :set_user

def edit
end

def create
  if @user.update user_params
     # Set success message
     # redirect to proper site
  else
     # Set error
     render :edit
  end
end


private

def set_user
  @user = User.find(params[:id])    # Rescue against ActiveRecord::RecordNotFound error
end

def user_params
  params.require(:user).permit(:firstname, :lastname)   # Here the strong parameters stuff happens
end

If you want to permit more parameters you just have to add them to the permit method call.

You got this error just for security reasons.

You can disable Strong Parameters with config.action_controller.permit_all_parameters = true but I highly recommend you to use this feature.

Upvotes: 0

Richard Peck
Richard Peck

Reputation: 76774

Because is_new? is from Toy, you have to use accepts_nested_attributes_for:

#app/models/user.rb
class User < ActiveRecord::Base
  has_many :toys
  accepts_nested_attributes_for :toys
end

#app/controllers/users_controller.rb
class UsersController < ApplicationController
  def edit
    @user = User.find params[:id]
  end

  def update
    @user = User.find params[:id]
    @user.update user_params
  end

  private

  def user_params
    params.require(:user).permit(:age, :email, toys_attributes: [:is_new])
  end
end

To get this to work in the view, you'll need to use the fields_for helper:

#app/views/users/edit.html.erb
<%= form_for @user do |f| %>
  <%= f.fields_for :toys, @user.toys do |t| %>
    <%= t.object.name %>
    <%= t.check_box :is_new %>
  <% end %>
  <%= f.submit %>
<% end %>

Upvotes: 1

Related Questions