Skip to content

# Step 11 — Reading Model

Gerald Goh edited this page Jul 26, 2020 · 19 revisions

Create Reading model

$ rails generate model api/reading bedroom:integer study:integer garage:integer living:integer kitchen:integer guest:integer consumption:integer available:integer saved:integer -j=false -y=false --skip-template-engine --no-helper
      invoke  active_record
      create    db/migrate/20200505184926_create_readings.rb
      create    app/models/reading.rb
      invoke    test_unit
      create      test/models/reading_test.rb
      create      test/fixtures/readings.yml

Add validation for Reading model

app/models/Reading.rb

class Reading < ApplicationRecord
  belongs_to :user
  validates :bedroom, presence: true
  validates :study, presence: true
  validates :garage, presence: true
  validates :living, presence: true
  validates :kitchen, presence: true
  validates :guest, presence: true
  validates :consumption, presence: true
  validates :available, presence: true
  validates :saved, presence: true
end

Edit user model

app/model/user.rb

class User < ApplicationRecord
  has_secure_password
  has_many :readings
  validates :name, presence: true, length: { minimum: 3, maximum: 100 }
  validates :email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }, uniqueness: true
  validates :units, presence: true
  validates :target, presence: true
end

Migrate DB

$ rails db:migrate
== 20200505184926 CreateReadings: migrating ===================================
-- create_table(:readings)
   -> 0.9477s
== 20200505184926 CreateReadings: migrated (0.9485s) ==========================

Generate a DB table to associate readings to user via migration

$ rails g migration add_user_id_to_readings user:references
      invoke  active_record
      create    db/migrate/20200505190744_add_user_id_to_readings.rb

Migrate association DB

$ rails db:migrate
== 20200505190744 AddUserIdToReadings: migrating ==============================
-- add_reference(:readings, :user, {:null=>false, :foreign_key=>true})
   -> 0.2544s
== 20200505190744 AddUserIdToReadings: migrated (0.2551s) =====================

Edit newly migrated DB file

db/migrate/timestamp_add_user_id_to_readings.rb

class AddUserIdToReadings < ActiveRecord::Migration[6.0]
  def change
    add_reference :readings, :user, null: false, foreign_key: true
  end
end

Generate Reading Controller for view to model association

$ rails generate controller api/v1/readings index create show destroy -j=false -y=false --skip-template-engine --no-helper
      create  app/controllers/readings_controller.rb
      invoke  erb
      create    app/views/readings
      invoke  test_unit
      create    test/controllers/readings_controller_test.rb
      invoke  helper
      create    app/helpers/readings_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    scss
      create      app/assets/stylesheets/readings.scss

In this command, you created a Readings controller in an api/v1 directory with an index, create and show. The index action will handle fetching all your readings, the create action will be responsible for creating new readings and the show action will fetch a single reading.

You also passed some flags to make the controller more lightweight, including:

  • -j=false which instructs Rails to skip generating associated JavaScript files.
  • -y=false which instructs Rails to skip generating associated stylesheet files.
  • --skip-template-engine, which instructs Rails to skip generating Rails view files, since React is handling your front-end needs.
  • --no-helper, which instructs Rails to skip generating a helper file for your controller.

Map the routes for the reading actions

config/routes.rb
.
.
  namespace :api do
    namespace :v1 do
      get 'readings', to: 'readings#index'
      get 'readings/create'
      get 'readings/show'
      get 'readings/destroy'
      get '/readings/:id', to: 'readings#show'
      get '/readings/user/:id', to: 'readings#list_readings_by_user'
      get '/user/:user_id/reading/:id', to: 'readings#list_reading'
    end
  end
.
.

Edit create and show in Readings controller

app/controllers/v1/readings_controller.rb

class Api::V1::ReadingsController < ApplicationController
  skip_before_action :verify_authenticity_token
  before_action :logged_in?

  def index
    @readings = Reading.all
    if @readings
      render json: {
        code: 200,
        data: Reading.all.as_json
      }
    else
      render json: @readings.errors
    end
  end

  def create
    @reading = current_user.readings.build(reading_params)
    if @reading.save
      render json: {
        code: 200
      }
    else
      render json: {
        code: 400,
        errors: @user.errors.messages
      }
    end
  end

  def show
    @reading = Reading.find(params[:id])
    if @reading
      render json: {
        code: 200,
        data: @reading.as_json
      }
    else
      render json: @reading.errors
    end
  end

  def destroy; end

  def list_readings_by_user
    @readingList = Reading.where(user_id: params[:id])
    if @readingList
      render json: {
        code: 200,
        data: @readingList.as_json
      }
    else
      render json: @readingList.errors
    end
  end

  def list_reading
    @read = Reading.find_by(user_id: params[:user_id], id: params[:id])
    if @read
      render json: {
        code: 200,
        data: @read.as_json
      }
    else
      render json: @read.errors
    end
  end

  private

  def reading_params
    params.require(:reading).permit(
      :bedroom,
      :study,
      :garage,
      :living,
      :kitchen,
      :guest,
      :consumption,
      :available,
      :saved
    )
  end
end