I'm trying to debug a controller that just won't play ball. I've narrowed it down to the strong parameters not working properly and so I've tried it out on the rails console.
params = ActionController::Parameters.new({
"user"=> {
"login"=>"username",
"password"=>"[FILTERED]"
},
"staff_id"=>"1"
})
This returns, as you'd expect:
=> {"user"=>{"login"=>"username", "password"=>"[FILTERED]"}, "staff_id"=>"1"}
So, I attempted to filter the parameters, like so...
params.require(:staff_id)
=> "1"
> params.require(:user).permit(:password,:login)
=> {"password"=>"[FILTERED]", "login"=>"username"}
That looks ok.
In my controller, I have:
def create
@staff=Staff.find(params[:staff_id])
@user = @staff.create_user(reg_params[:user])
DISASTER
Now, at the point of the disaster, the user object @user should have a login and password set but It doesn't. I've tried logging the @user object at that point, it's properties are nil.
Why isn't my user object being created properly? If I remove the DISASTER, it creates a database record with blank fields, except for the timestamps.
Models:
class Staff < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_one :staff
end
Schema:
ActiveRecord::Schema.define(version: 20150909102012) do
create_table "staff", force: :cascade do |t|
t.string "qualifications"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
end
add_index "staff", ["users_id"], name: "index_staff_on_users_id"
create_table "users", force: :cascade do |t|
t.string "login"
t.string "username"
t.string "password"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
It routes to the custom controller ok. Here's the route:
Rails.application.routes.draw do
resources :staff do
resource :user, shallow: true, controller: 'staff_register'
end
resources :users
There's nothing else in the app because it's just an experiment to help me work on a bigger problem I've been struggling with.
Basically, I want to be able to link a staff model to a user model. I think I've done that ok, I just need help figuring out the strong parameters bit.
EDIT: here's the form for the nested resource:
<%= form_for @user, :url => staff_user_path(@staff) do |f| %>
<% if @user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% @user.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :login %><br>
<%= f.text_field :login %>
</div>
<div class="field">
<%= f.label :password %><br>
<%= f.text_field :password %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
In this line:
@user = @staff.create_user(reg_params[:user])
reg_params
already gives you hash with all the permitted parameters:
{"password"=>"[FILTERED]", "login"=>"username"}
There is no user
key there, hence reg_params[:user]
is just nil
. Instead you need to do:
@user = @staff.create_user(reg_params)
Now, you do not need to worry about staff_id
here, as you are executing create_user
method on already existing @staff
model. This method will take care of the association.