I'm struggling to understand the relationship that owner = create(:user, device_token: device_token)
has to owner: {device_token: device_token}
, I usually use user_id
for this association.
2. What is the device_token
method in the controller is doing.
describe 'POST /v1/events' do
it 'saves the address, lat, lon, name, and started_at date' do
date = Time.zone.now
device_token = '123abcd456xyz'
owner = create(:user, device_token: device_token)
post '/v1/events', {
address: '123 Example St.',
ended_at: date,
lat: 1.0,
lon: 1.0,
name: 'Fun Place!!',
started_at: date,
owner: {
device_token: device_token
}
}.to_json, { 'Content-Type' => 'application/json' }
event = Event.last
expect(response_json).to eq({ 'id' => event.id })
expect(event.address).to eq '123 Example St.'
expect(event.ended_at.to_i).to eq date.to_i
expect(event.lat).to eq 1.0
expect(event.lon).to eq 1.0
expect(event.name).to eq 'Fun Place!!'
expect(event.started_at.to_i).to eq date.to_i
expect(event.owner).to eq owner
end
end
Controller Code:
def create
@event = Event.new(event_params)
if @event.save
render
end
end
private
def event_params
{
address: params[:address],
ended_at: params[:ended_at],
lat: params[:lat],
lon: params[:lon],
name: params[:name],
started_at: params[:started_at],
owner: user
}
end
def user
User.find_or_create_by(device_token: device_token)
end
def device_token
params[:owner].try(:[], :device_token)
end
end
There's a number of ways you can identify uniquely identify a record in a database. Using the id
field is the most common - but if you've got another way to uniquely identify a user, then you can use that, too. Normally, you don't show a user what their ID number is in the database. But, if you want to give them a way to uniquely identify themselves, you could create another field which is unique for each user - such as a membership_number
or similar. It seems like in your case, device_token
is a field that uniquely identifies a user.
So, your database cares about the user_id
field - that's what it uses to tie an Event
to a specific User
(aka, the owner). If your users knew their id, then they could pass in that, rather than their device_token
, and everything would be fine. But they don't know it.
So, they pass in their devise_token
. You use that to fetch the user from the database, and then you know that user's id. Then, you can store that user's id in the user_id
field of your Event
model.
def user
User.find_or_create_by(device_token: device_token)
end
This method is the one that gets a user based on a devise_token
. And then this method:
def event_params
{
address: params[:address],
ended_at: params[:ended_at],
lat: params[:lat],
lon: params[:lon],
name: params[:name],
started_at: params[:started_at],
owner: user
}
end
In particular, the line: owner: user
calls that method above. From that point, Rails handles it under the hood and makes sure your user_id is set correctly.
UPDATE AFTER YOUR COMMENT:
device_token
is being passed in as a parameter. It is also the name of a field in the User model. So, a single row in the user table might look like this:
id: 24, first_name: fred, last_name: flintstone, device_token: 123abc, address: bedrock, etc.
the method:
def user
User.find_or_create_by(device_token: device_token)
end
is saying: go to the User's table in the database, try to find a User which has a device_token
that has the value that was passed in as a parameter, and if we can't find one, then create one.
So in this line: User.find_or_create_by(device_token: device_token)
, the first reference to device_token
is the key of a hash, and it refers to the field called device_token
in your User model.
The second reference to device_token
is a call to this method:
def device_token
params[:owner].try(:[], :device_token)
end
which fetches the device_token
from the parameters passed in. This method basically says: Look in the params hash at the value inside the owner
key. See if the owner
key contains a device_token
. If it does, return that device_token
, and if it doesn't return nil
. It does this using the try
method, which you can read more about here: http://apidock.com/rails/Object/try