I am building a Rails project where I have a user, and that user has many Tests
(it's like a Trivia game). I have a UsersController
where I query the user (going to implement login later).
In my view I have a button which "starts" the test. I need to associate the user with a test, because my User has_many Tests
(user_id is a foreign key on tests). My question is, how do I pass my @user
object to my TestsController
so I can associate the created test with the logged in user?
Here is my UsersController
:
class UsersController < ApplicationController
def show
@user = User.find(1)
end
def start_test
redirect_to tests_path
end
end
In my users show view I have:
<p>Welcome <%= @user.name %>!</p>
<%= button_to "Start Test", users_start_test_path %>
When the button is clicked I redirect to tests_path
which is in TestsController:
class TestsController < ApplicationController
def index
# here I need to create the Test belonging to the user
end
end
I am new to Rails and don't know how to pass that @user
to TestsController
so I can create the test belonging to the user. Theoretically I don't even need the whole @user
, just the id
. Any help would be greatly appreciated.
CodePudding user response:
The controllers are standalone. They cann't share variables. You could try to send user id intro the request to controller TestsController (or better use an authentication system). Or directly in the TestsController calls User.find(1) again.
CodePudding user response:
The only variable you can pass between controllers is a parameter through the routing (or the session).
So you can have a HTML Form that passes a body to an action inside a different controller OR for what I see in your case by visiting a route and pass a friendly query string parameter, like an ID.
So you could:
<%= button_to "Start Test", users_start_test_path(user_id: @user.id) %>
And then in your TestController:
class TestsController < ApplicationController
def index
@user = User.find params[:user_id]
end
end
CodePudding user response:
I don't like to pass the current_user variable because it can then be hijacked.
This is how I would set the TestsController
class TestsController < ApplicationController
def index
@tests = current_user.tests
end
def new
@test = current_user.tests.new
end
def create
current_user.tests.create(test_params)
end
def show
@test = current_user.tests.find(params[:id]) # this will only find tests scoped to that user
end
def edit
@test = current_user.tests.find(params[:id]) # this will only find tests scoped to that user
end
def update
@test = current_user.tests.find(params[:id]) # this will only find tests scoped to that user
@test.update(test_params)
end
def test_params
params.require(:test).permit()
end
end
This way now you have the test scoped to the user. I am assuming that you have device for user management