1

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
ideahed
  • 179
  • 3
  • 11

1 Answers1

0

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

joshua.paling
  • 13,762
  • 4
  • 45
  • 60
  • Thanks sir, and what is the `device token` method doing? To further clarify the API is for an iOS app so it uses the unique device token to determine that it's the right user and users device.Where is it being called in the controller? The syntax is a little unclear within the method as well. What's clear is the params[owner] property is being passed into the `devise-token` method, but not sure what it is retuning. – ideahed Nov 09 '14 at 23:02