Basic ActiveRecord Methods
Tags: rails, ruby, beginners, webdev
Published: 2023-02-14 22:44:09

Today I am working on some basic db calls to tough on some of those simple concepts that feels like I learned ages ago. Here is the quiz and my answers below:

## ActiveRecord Lookups Quiz

Without looking for help online write the following queries:

### 1. Find an author with an `id` of `9`.
  **Answer:** Author.find(9)
  **Why:** Using the `Find` method only takes `id` numbers as inputs and returns a single value based on that input.

### 2. Find all authors with a `last_name` of `Brown`.
  **Answer:** Author.find_by(last_name: 'Brown')
  **Why:** `find_by` searches by attributes of the model that it is called on and returns the first instances where the condition is met.

### 3. Find the first author with a `last_name` of `Brown`.
  **Answer:** Author.find_by(last_name: 'Brown)
  **Why:** refer back to question 2

### 4. Find all articles created in the last 5 days.
  **Answer:** Article.where("created_at >= ?", 5.days.ago)
  **Why:** Here I decided to use sql paired with AR (ActiveRecord) to simplify my code. Using `.where` was the best choice in my opinion because I am searching the whole database to see is my condition (article being created in the last 5 days) has been met. If there haven't been any articles created then this method should return an empty array.

## Using only one call to the database:

### 5. Find all users with a `last_name` of 'Brown' and return the first user with a `first_name` of 'Nancy'.
  **Answer:** User.where(last_name: 'Brown').find_by(first_name: 'Nancy')
  **Why:** `.where` searches the db for users where the `last_name` == 'Brown'. This returns an array, on that array I then am using find_by to find the first instance where the first_name is 'Nancy'.

### 6. Find all articles created in the last 5 days. Display the article title and author's last_name for each article.
  - Article.where(created_at: 5.days.ago..Time.now)
                  .includes(:author)
                  .select("title, users.last_name as author_last_name")
                  .map { |article| [article.title, article.author_last_name] }

### Bonus Round

### 7. What's the danger of using `update_attribute` vs `update_attributes`?
  Answer and Why: 'update_attribute' changes a singular attribute WITHOUT checking against validations and callbacks. While 'update_attributes' changes multiple the attributes and checks the validations and callbacks. So the danger would be that using update_attribute' you may accidentally save an attribute that is an invalid value.

### 8. Imagine we are creating and loading users based on data received from an external service (`attributes` in this example).
  
  Refactor the method below to use `.first_or_initialize` and `.tap`:

  ```ruby
  def self.find_or_create_from_external_service(attributes = {})
    user = User.find_by_login(attributes[:login])
    if user.nil?
      user = User.create(login: attributes[:login], email: attributes[:email])
    end

    user
  end
  ```

refactor:
  ```ruby
  def self.find_or_create_from_external_service(attributes = {})
    User.where(login: attributes[:login]).first_or_initialize.tap do |user|
      user.update(email: attributes[:email]) if user.new_record?
      user.save
    end
  end
```