Neb19

Joined

50 Experience
0 Lessons Completed
0 Questions Solved

Activity

Posted in Question about SQL Queries and my routes

Hello

I'm a beginner on Rails and I have questions about my forum project.

I have some Categories which can contain many Themes. And Themes can contain many Topics

Here is what I want with my routes :

localhost/:category_slug => categories#show => list all Themes inside this Category
localhost/:category_slug/:theme_slug => themes#show => list all Topics inside this Theme
localhost/:category_slug/:theme_slug/:topic_id => topics#show => display the corresponding Topic

And I want to render a 404 if one of each resources doesn't exist.

An example if I want to reach the Topic which is associated to my Theme "dark-souls", itself associated to the Category "video-games" :

localhost/video-games/dark-souls/1.

Moreover, I have a shared view in a helper which contains the list of all my Categories and it's displayed on all my pages.

I successfully did what I want but I dont know if I did it in the good way and I want to know if it's correct or not. I would like to have an external mind and some advises on it.

ApplicationController

class ApplicationController < ActionController::Base

  helper_method :current_user
  helper_method :is_logged?
  helper_method :get_all_categories

  def current_user
    session[:user_id] || nil
  end

  def is_logged?
    not current_user.nil?
  end

  def redirect_if_not_logged
    is_logged? or redirect_to login_path
  end

  def render_404
    raise ActionController::RoutingError.new("Resource not found")
  end

  def get_all_categories
    @categories = Category.all
  end

end

CategoriesController

class CategoriesController < ApplicationController

  before_action :redirect_if_not_logged
  before_action :get_all_categories, only: :show

  def show
    @category = Category.includes(:themes).find_by(slug: params[:category_slug])
  end

end

ThemesController

class ThemesController < ApplicationController

  before_action :redirect_if_not_logged
  before_action :get_all_categories, only: :show

  def show
    @theme = current_category.themes.find_by(slug: params[:theme_slug]) or render_404
  end

  private

  def current_category
    Category.includes(themes: :topics).find_by(slug: params[:category_slug]) or render_404
  end

end

TopicsController

class TopicsController < ApplicationController

  before_action :redirect_if_not_logged
  before_action :get_all_categories, only: :show

  # GET /:category_slug/:theme_slug/:topic_id
  def show
    @topic = current_theme.topics.find_by(id: params[:topic_id]) or render_404
  end

  private

  def current_category
    Category.includes(themes: :topics).find_by(slug: params[:category_slug]) or render_404
  end

  def current_theme
    current_category.themes.find_by(slug: params[:theme_slug]) or render_404
  end
end

Logs

Here are the logs when i try to reach, for instance, /video-games/the-last-of-us-part-2/38

Started GET "/video-games/the-last-of-us-part-2/38" for 127.0.0.1 at 2021-03-16 14:16:52 +0100
Processing by TopicsController#show as HTML
  Parameters: {"category_slug"=>"video-games", "theme_slug"=>"the-last-of-us-part-2", "topic_id"=>"38"}
  Category Load (0.7ms)  SELECT "categories".* FROM "categories" WHERE "categories"."slug" = $1 LIMIT $2  [["slug", "video-games"], ["LIMIT", 1]]
  ↳ app/controllers/topics_controller.rb:58:in `current_category'
  Theme Load (0.7ms)  SELECT "themes".* FROM "themes" WHERE "themes"."category_id" = $1  [["category_id", 3]]
  ↳ app/controllers/topics_controller.rb:58:in `current_category'
  Topic Load (0.7ms)  SELECT "topics".* FROM "topics" WHERE "topics"."theme_id" IN ($1, $2, $3)  [[nil, 1], [nil, 2], [nil, 9]]
  ↳ app/controllers/topics_controller.rb:58:in `current_category'
  Theme Load (0.5ms)  SELECT "themes".* FROM "themes" WHERE "themes"."category_id" = $1 AND "themes"."slug" = $2 LIMIT $3  [["category_id", 3], ["slug", "the-last-of-us-part-2"], ["LIMIT", 1]]
  ↳ app/controllers/topics_controller.rb:62:in `current_theme'
  Topic Load (0.5ms)  SELECT "topics".* FROM "topics" WHERE "topics"."theme_id" = $1 AND "topics"."id" = $2 LIMIT $3  [["theme_id", 1], ["id", 38], ["LIMIT", 1]]
  ↳ app/controllers/topics_controller.rb:8:in `show'
  Rendering layout layouts/application.html.erb
  Rendering topics/show.html.erb within layouts/application
  ActionText::RichText Load (0.8ms)  SELECT "action_text_rich_texts".* FROM "action_text_rich_texts" WHERE "action_text_rich_texts"."record_id" = $1 AND "action_text_rich_texts"."record_type" = $2 AND "action_text_rich_texts"."name" = $3 LIMIT $4  [["record_id", 38], ["record_type", "Topic"], ["name", "content"], ["LIMIT", 1]]
  ↳ app/views/topics/show.html.erb:8
  Rendered topics/show.html.erb within layouts/application (Duration: 2.5ms | Allocations: 1178)
[Webpacker] Everything's up-to-date. Nothing to do
  Rendered shared/_aside_user.html.erb (Duration: 0.2ms | Allocations: 118)
  Category Load (0.8ms)  SELECT "categories".* FROM "categories"
  ↳ app/views/shared/_aside_infos.html.erb:10
  Rendered shared/_aside_infos.html.erb (Duration: 1.9ms | Allocations: 868)
  Rendered layout layouts/application.html.erb (Duration: 25.8ms | Allocations: 7657)
Completed 200 OK in 36ms (Views: 24.8ms | ActiveRecord: 4.7ms | Allocations: 12530)

Conclusion

All is working fine. I mean, if I try to access to a theme which exists but under a category path that doesn't exist I get a HTTP 404, so this is what I want. But I don't know if it's really clean. I mean, I would like to know best practices and in my mind it seems good but there are maybe too many SQL requests ?

Does it look like normal for you ? or do I need to change something?

=> Sorry if my english is not good. Thank you to read me