There are tons of these, especially for Rails 4.0 and Rails 3.x. I am new to nested routing and I find it very difficult, especially with forms.
So I have the following:
Routes
resources :users do
resources :api_keys, path: '/developmentcenter'
end
The relationship here is: user has many api keys where api key belongs to user.
Controller
class ApiKeysController < ApplicationController
before_action :authenticate_user!
def new
@user = User.find(params[:user_id])
@api_key = ApiKey.new(:user => @user)
end
def index
@user = User.find(params[:user_id])
@api_key = @user.api_keys
end
def create
@user = User.find(params[:user_id])
@api_key = ApiKey.new(create_new_api_key)
create_api_key(@api_key, @user)
end
def destroy
@user = User.find(params[:user_id])
destroy_api_key(@user)
end
private
def create_new_api_key
params.permit(:api_key, user_attributes: [:id])
end
end
The above is pretty basic. create_api_key
is a method that does something on save, or does something else on failure to save. While destroy_api_key
Just find the api key based on the user id and deletes it, does something on success and something on failure.
So now lets create a form - which has a single button for creating the API key.
<h2>Create a new Key</h2>
<%= form_for ([@user, @api_keys]) do |f| %>
<p class="button"><%= f.submit "Generate API Key" %></p>
<% end %>
All we need is a single submit button that upon click, creates a new api key for the user whom is logged in.
But wait we have a an error:
First argument in form cannot contain nil or be empty
This error takes place at:
<%= form_for ([@user, @api_keys]) do |f| %>
So - I have looked at every single one of the stack questions (well most) that deal with this error, I have changed my controller based on a few, to what you see above. I have even look at the form helpers docs in the rails manual.
I cannot figure this out.
It is telling you that @user is empty or nil in the context it is using. Either this is a user who has not been created in the DB yet, or your
User.find
call is not working to return an actual user. The form needs to know who @user is before it can create a nested resource (@api_key) for it. Your `create_api_key' is completely wrong. You need to whitelist your params first, then find the user in the DB (or create them), then you can use the @user instance variable to create a form for that user to create a key. I think if you do it right, you shouldn't need to call @api_keys in the beginning of the form if you defined the relationships in your models (has_many or has_one, belongs_to etc.). Can you post the web server console output when you visit that page? First off you are callingevery time in your controller. You should DRY that up with a before_action.
Then at the top of the controller you would have:
Also you should make your .permit a method that returns a variable called api_key_params:
That way you have the things you want returned in a whitelist. To access these params you just call the method. You can specify a param you want returned from the method like my
set_user
example. But it also gives you the ability to do things like:That way the Api_key.new gets the user and creates the key. You don't show how or where you generate the key itself. If it gets created by some method, you should put that in the model for Api_key. There are some other things about your code that are confusing without seeing the rest of your files.