Rails 3 has_many, как создать объект и его отношения из действия индекса

#ruby-on-rails #ruby-on-rails-3 #has-many

#ruby-on-rails #ruby-on-rails-3 #имеет-many

Вопрос:

У меня есть группы, коды и пользователи.

ключ / коды позволят пользователю выполнять какие-либо действия с группой. Я нахожусь в действии Band #show и мне нужно сгенерировать код, а затем связать этот код с пользователем и группой.

итак:

Код принадлежит_to:band, принадлежит_to:пользовательская группа has_many :коды Пользовательская группа has_many:коды

Итак, теперь мне нужно использовать form_for (я думаю) для создания кнопки, которая при нажатии выполняет следующее:

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

Если нет:

  • Создает 6-значный буквенно-цифровой ключ / код (я знаю, что ActiveSupport может это сделать: <%= SecureRandom.hex(3)%> но это должно быть в модели или контроллере)
  • Установите правильные ассоциации, этот код работает для этого пользователя и этой группы. Я использую Devise, поэтому у меня есть доступ к методу current_user
  • и вернуть пользователя в группу#показать действие

Если у пользователя уже есть код для этого диапазона, то ему выдается сообщение об ошибке «У вас уже есть код»

Я хочу в конечном итоге выполнить этот вызов с помощью Ajax, чтобы избежать перезагрузки страницы, но пока я просто пытаюсь создать функцию.

Комментарии:

1. Проверьте документацию RoR на наличие ассоциаций guides.rubyonrails.org/association_basics.html

2. Я это сделал. И хотя это помогает, и я смог построить свои модели на его основе, я затрудняюсь со следующими шагами. Даже какое-то направление было бы круто, на какие типы вещей мне следует обратить внимание?

Ответ №1:

Во-первых, я бы создал следующий маршрут в вашем routes.rb:

 resources :bands do
  post :add_code, :on => :member
end
  

Это создаст дополнительный маршрут, выглядящий следующим образом:

 add_code_band_path POST   /bands/:id/add_code(.:format)  {:action=>"add_code", :controller=>"bands"}
  

Затем из ваших представлений вы можете использовать вспомогательный метод button_to для отправки post-запроса, подобного этому:

 <%= button_to "Add Code", add_code_band_path(@band), :method => :post %>
  

Когда пользователь нажимает на эту кнопку, вы можете обработать все остальное из действия контроллера следующим образом:

 class BandsController < ApplicationController
  ...

  def add_code
    @band = Band.find(params[:id])
    @code = current_user.codes.find_or_create_by_band_id(@band.id)
    render :action => :show
  end
  

Наконец, фактический рандомизированный код, который я бы сгенерировал из обратного вызова before_create из самой модели кода, вот так:

 class Code < ActiveRecord::Base
  ...

  before_create :generate_code

private
  def generate_code
    self.code = SecureRandom.hex(3)
  end
end
  

Тогда, если вы считаете, что это необходимо, вы также можете добавить другие проверки, например, показывать кнопку «Добавить код» только при отсутствии существующего кода или, возможно, добавлять сообщения об ошибках, если пользователь пытается добавить другой код для той же группы, но я оставляю это вам. Помощник button_to также поддерживает Ajax с помощью :remote => true , поэтому вы можете развивать его так, как хотите.

Комментарии:

1. Данне, это огромная помощь. Я изо всех сил пытался понять, как это сделать, и это делает это. Единственная проблема, которую я вижу, заключается в том, что, похоже, он не создает код. Нужно ли добавлять @code = Code.new в действие show в контроллере?

2. Мне жаль, что я больше копался в find_or_create_by, и я думаю, возможно, я недостаточно передаю ему. api.rubyonrails.org/classes/ActiveRecord/Base.html говорится о передаче ему дополнительных методов…

3. Я смог решить свою проблему с помощью этого небольшого изменения: find_or_create_by_band_id (@band.id , :user_id => current_user.id )

4. Хм, это было странно. Атрибут user_id должен был быть установлен автоматически, пока вы создавали код из ассоциации current_user.codes. Ну что ж, рад, что у вас получилось.

Ответ №2:

Попробуйте в вашей группе / пользовательских кодах, has_many: через

Вам придется создать таблицу объединения и модель объединения, но я думаю, это то, что вы ищете.