2015-12-27 5 views
3

Это мой первый вопрос, так голый со мной и с моим английским, поскольку это не мой родной язык. У меня есть 3 модели (Клиент, Пользователь и Администратор) без контроллероввставить данные через третью таблицу

class Admin < ActiveRecord::Base 
    validates_presence_of :username, :user_id, :client_id 
    belongs_to :client 
    belongs_to :user 
end 

class Client < ActiveRecord::Base 
    validates_presence_of :name 
    has_many :admins 
    has_many :users, :through => :admins 
end 

class User < ActiveRecord::Base 
    validates_presence_of :name, :email 
    has_many :admins 
    has_many :clients, :through => :admins 
end 

Так что, когда я делаю

u = User.first.clients.new(name: 'First Client') 
u.save 

Тогда все работает отлично

(0.2ms) begin transaction SQL (0.6ms) INSERT INTO "clients" ("name", 
"created_at", "updated_at") VALUES (?, ?, ?) [["name", "First 
Client"], ["created_at", "2015-12-27 10:38:47.790787"], ["updated_at", 
"2015-12-27 10:38:47.790787"]] (98.3ms) commit transaction => 
true 

, но когда я пытаюсь см.

2.2.2 :130 > User.first.clients 
User Load (0.5ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT 1 Client Load (0.2ms) SELECT "clients".* FROM "clients" INNER JOIN "admins" ON "clients"."id" = "admins"."client_id" WHERE "admins"."user_id" = ? [["user_id", 1]] => #<ActiveRecord::Associations::CollectionProxy []> 

Итак, как мне вставить данные в третью таблицу? У меня есть много об этом, но нет решения, так как усложнение здесь состоит в том, что в третьей таблице Admin также есть обязательная колонка Username. Также как вставить данные в таблицы User и Client через этот стол Admin. Любое решение будет оценено по достоинству.

+0

Если вы проверяете журналы, вы можете увидеть, что при сохранении нового клиента, он будет создавать только 'под клиентом запись, но не' admin' записи , В то время как поисковый запрос просматривает таблицу «Admin» и не может найти никаких записей. Попробуйте что-то вроде: 'c = Client.create (name:" name ")', а затем 'User.first.clients << c' – Kkulikovskis

+0

Yea спасибо за ответ @Kkulikovskis Я уже пробовал то, что вы сказали, но в этом проблема в том, когда я делаю это, это дает мне, и ошибка имени пользователя не может быть пустым, которая находится в модели администратора, и когда я пытаюсь указать имя пользователя, а затем он говорит неизвестный атрибут «имя пользователя» –

+0

О, извините. Не заметил поля имени пользователя. В этом случае я не вижу другого способа, кроме как просто создать каждого из них отдельно. например 'c = Client.new (имя: имя); u = User.first; Admin.create (username: username, client: c, user: u) ' – Kkulikovskis

ответ

0

При создании клиента как этот u = User.first.clients.new(name: 'First Client')
Он вставить строку и столбец только name, created_at, updated_at

писать И когда вы звоните User.first.clients, как это,
Это найти админов, что User.first имеет. а затем находить клиентов администраторами.

Итак, нет администраторов, которые имеют отношение к клиенту, который вы создали в первую очередь.

Вы должны установить admin_id (этот столбец может быть, существуют в таблице клиентов) при создании клиента, как этот

user = User.first 
client = user.clients.create(name: 'xxx') 
user.clients << client 
+0

Это не совсем так, так как 'has_many through' должен позаботиться об этом, явно не указав admin_id. – Kkulikovskis

+0

'... clients.new (...)', нет метода 'new()' в массиве отношений ActiveRecord :: Associations :: CollectionProxy', только 'build'. –

+0

@Kkulikovskis Нет, как activerecord определяет, какие администраторы выбирают при создании нового клиента? У пользователя много админов, а код не указывает admin_id, вы пробовали в консоли? –

0

Позвольте мне ответить на ваш вопрос один на один

1: Так как я вставить данные в третьей таблице

Как уже упоминалось в official document

4.3.1 Методы Добавлен has_many

При объявлении has_many ассоциации, объявляющий класс автоматически получает 16 методов, связанные с ассоциацией:

collection<<(object, ...) 

В вашем случае

u = User.first.clients.new(name: 'First Client') 

Должно быть

clients = User.first.clients 
client = Client.new(name: 'First Client') 
clients << client 

Коллекция < < метод добавляет один или несколько объектов в коллекции от установки их внешние ключи к первичному ключу вызывающей модели.


2: User.first.clients Как это работает

collection(force_reload = false) 

Метод сбора возвращает массив всех связанных с объектов. Если нет связанных объектов, он возвращает пустой массив .

Надеюсь, что это поможет вам правильно понять !!!

+0

Проблема, как я понимаю, заключается в том, что вам нужно объявить «имя пользователя» для ассоциации «Admin». Вот почему метод '<<' не принесет пользы. Это приведет к ошибке проверки, как упоминалось ранее в комментариях. – Kkulikovskis

+0

транзакция отката ActiveRecord :: RecordInvalid: сбой проверки: имя пользователя не может быть пустым. Это дает мне ошибку проверки для администратора, поскольку этот ответ уже предлагается в комментариях. –

+0

@MalwareSkiddie: Это должно быть потому, что его явно бросает ** Проверка не выполнена: Имя пользователя не может быть пустым ** Просто удалите проверку. Это сработало !!!. – VKatz

1

Я знаю, что я уже говорил это в комментариях, но он должен обязательно работать:

Поскольку Admin модель проверки для username это не будет возможно просто добавить client к user.clients коллекции, так как он будет приведет к ошибке ActiveRecord :: Validation.

Вместо этого вы должны сделать эти шаги отдельно или создать метод, который будет делать их все сразу:

  1. Сделать объект пользователя: user = User.create(name: "name", email: "[email protected]")
  2. Сделать объект клиента client = Client.create(name: "name")
  3. Сделать объект администратора admin = Admin.create(username: "username", user: user, client: client)

это создаст необходимые записи в таблице, поэтому, когда вы проверите user.clients, он будет выглядеть f или все записи в таблице admins, где user_id = user.id, а затем получить все соответствующие клиенты.

Если вы делаете это в консоли, после выполнения всех шагов сделать перезагрузку на вашем экземпляре пользователя, чтобы увидеть клиентов: user.reload.clients

Чтобы сохранить ваш код более организованным и делать все эти шаги сразу , вы можете обернуть это в метод экземпляра пользователя.Например:

для класса пользователя

def add_client(client_name, admin_username) 
    client = Client.create(name: client_name) 
    admin = Admin.create(username: admin_username, client: client, user: self) 
end 
+0

спасибо, что это работает, но вместо того, чтобы создавать отдельно, вы можете указать способ создать это простым способом, так как это было бы легко для меня, когда я сделаю для этого контроллеры. –

+0

@MalwareSkiddie Я обновил свой ответ. – Kkulikovskis

+0

спасибо за помощь :) оценен –