ideahed
ideahed

Reputation: 179

Rails Associations Rspec

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

Upvotes: 1

Views: 67

Answers (1)

joshua.paling
joshua.paling

Reputation: 13952

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

Upvotes: 0

Related Questions