New Discussion

Notifications

You’re not receiving notifications from this thread.

Question about SQL Queries and my routes

0
Rails

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

Join the discussion
Create an account Log in

Learning Ruby on Rails? Join our newsletter.

We won't send you spam. Unsubscribe at any time.