Как извлечь данные из двух таблиц, используя «соединения»? - PullRequest
2 голосов
/ 13 марта 2020

Я новичок в Ruby -on-Rails, и я начал исследовать ActiveRecords. И я сталкиваюсь с одной проблемой.

У меня есть две таблицы: todo_lists и users. Первый имеет следующие записи: title, description, user_id, deadline. А у второй только одна запись: name. Я хочу получить таблицу, которая содержит следующие записи: title, description, name, deadline, т.е. объединить две таблицы и поставить user вместо user_id. Я пытаюсь решить эту проблему, используя joins:

TodoList.joins(:user).select("todo_lists.title, todo_lists.description, users.name, todo_lists.deadline")

Но я получаю новый ActiveRecord::Relation без users.name:

[#<TodoList id: nil, title: "This is title", description: "This is description", deadline: "2020-03-13 18:59:58">]

Это мои todo_list.rb и user.rb файлы:

class TodoList < ApplicationRecord
    belongs_to :user
end

class User < ApplicationRecord
    has_many :todo_lists
end

schema.rb файл:

ActiveRecord::Schema.define(version: 2020_03_13_183504) do

  create_table "todo_lists", force: :cascade do |t|
    t.string "description", null: false
    t.integer "user_id", null: false
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.boolean "is_disabled"
    t.datetime "deadline"
  end

  create_table "users", force: :cascade do |t|
    t.string "name", null: false
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

  add_foreign_key "todo_lists", "users"
end

Может кто-нибудь помочь мне решить эту проблему?

Ответы [ 2 ]

1 голос
/ 13 марта 2020

Если вам нужно получить доступ к имени пользователя из каждого объекта в TodoList::ActiveRecord_Relation, вы можете использовать AS и дать правильное имя, что позволяет использовать его как метод из одной записи в ActiveRecord_Relation, содержащей имя пользователя:

TodoList.joins(:user).select("..., users.name AS user_name").first.user_name

В противном случае вы можете использовать as_json, который возвращает массив, содержащий данные каждой записи в виде ha sh, где каждый ключ - это столбец, а значение - соответствующие значения. в операторе выбора:

TodoList.joins(:user).select("todo_lists.description, users.name").as_json
# [{"id"=>nil, "description"=>"1st", "name"=>"user1", ...},
#  {"id"=>nil, "description"=>"2nd", "name"=>"user2", ...}]
0 голосов
/ 14 марта 2020

Себастьян Пальма - хороший ответ на заданный вопрос. В частности, он спросил, как решить эту проблему, используя joins.

Тем не менее, я думаю, что традиционный подход ActiveRecord к этой проблеме заключается в использовании ваших моделей и ассоциаций.

Вы можете добавить метод user_name к модели TodoList следующим образом:

class TodoList < ApplicationRecord
  belongs_to :user

  def user_name
    user.name
  end
end

Теперь любой экземпляр TodoList будет возвращать имя своего связанного пользователя независимо от того, как его запрашивали.

Чтобы избежать сценария запроса n + 1, вы можете использовать preload(:user) при запросе списков TodoLists. Например, этот код сделает 2 запроса для получения последних 10 списков TodoList и связанных с ними пользователей.

TodoList.preload(:user).last(10)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...