ruby-on-rails - 双 has_many 属性

标签 ruby-on-rails ruby-on-rails-4 activerecord

我是 Rails 的初学者,无法找到解决问题的正确方法。

我有三个模型:对话、参与者、消息,它们具有以下属性:

对话 :

module Messenger
  class Conversation <ActiveRecord::Base

    has_many :participants, :class_name => 'Messenger::Participant'

    def messages
      self.participants.messages.order(:created_at)
    end
  end
end

参与者:
module Messenger

  class Participant <ActiveRecord::Base

    has_many :messages, :class_name => 'Messenger::Message'

    belongs_to :conversation, :class_name => 'Messenger::Conversation'

  end
end

信息 :
module Messenger

  class Message <ActiveRecord::Base

    default_scope {order(:created_at)}
    default_scope {where(deleted: false)}

    belongs_to :participant, :class_name => 'Messenger::Participant'

  end
end

我的问题是我试图制作一个单一的表单来创建一个包含第一条消息的对话。表格如下所示:
= form_for @conversation, url: messenger.conversations_create_path do |f|
  .row
    .col-md-12.no-padding
      .whitebg.padding15
        .form-group.user-info-block.required
          = f.label :title, t('trad'), class: 'control-label'
          = f.text_field :title, class: 'form-control'

        .form-group.user-info-block.required
          = f.label :model, t('trad'), class: 'control-label'
          = f.text_field :model, class: 'form-control'

        .form-group.user-info-block.required
          = f.label :model_id, t('trad'), class: 'control-label'
          = f.text_field :model_id, class: 'form-control'

        = fields_for @message, @conversation.participants.message do |m|
          = m.label :content, t('trad'), class: 'control-label'
          = m.text_area :content, class:'form-control'

  .user-info-block.action-buttons
    = f.submit t('trad'), :class => 'btn btn-primary pull-right'

我尝试了很多方法来简化这个表单,但是我遇到了一些我不知道如何正确使用 rails 来修复的问题。

我试过使用 Field_for在我的对话表单中包含一条消息,但由于我的数据库中没有保存任何内容,但似乎我无法将消息链接到不存在的参与者。

所以基本上我希望我的第一个表单在经过验证后创建一个对话,将当前用户链接到该对话并将消息链接到该第一个用户,但我认为有一些方法可以使用框架来做到这一点,我不想手动完成。

实现这一目标的正确方法是什么?我是否处于良好的 rails 上,还是应该更改或添加一些内容?

编辑:为了更容易理解,参与者获得了一个 user_id 和一个 session_id,这意味着这是一个关系表。我无法调整模型的属性以使其更容易,因为出于安全原因我必须保持这种方式。

最佳答案

留言需要belong_to直接对话,因为当参与者有多个对话时,您需要消除歧义。

因此,完成此操作后,您可以使用以下命令在 Controller 中构建对话的默认消息

@conversation.messages.build(participant: @conversation.participants.first)

这很罗嗦,所以你可以添加几个模型方法来减少 Controller 调用
@conversation.build_default_message

在这种情况下,您想要创建一个对话,但它也需要创建一个带有用户输入的消息。所以Conversation需要代表Message接受属性。您可以使用 accepts_nested_attributes_for 来做到这一点
class Conversation
  accepts_nested_attributes_for :messages
end

这将允许您使用 1 个或多个关联消息创建对话
Conversation.create(
  ..., 
  messages_attributes: [
    { participant_id: 1, content: 'question' } 
  ]
)

关于ruby-on-rails - 双 has_many 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41825589/

相关文章:

javascript - rails : Nested remote form doesn't work on page load

jquery - 如果页面处于事件状态,则更改 li 类

ruby-on-rails - Rails CanCan gem 重构能力类

javascript - Rails4 - 如何通过Ajax安全地接收和发送JSON数据并存储它?

ruby-on-rails - matches_any 在使用 Arel 为数据表编写自定义过滤器的空数组上抛出异常

ruby-on-rails - Rails 4 - Carrierwave 图像未上传

ruby-on-rails - 如何序列化 ActiveModel 错误以供以后翻译?

ruby-on-rails - rake 分贝 :test:prepare in Rails 3 app fails with file not found

ruby-on-rails - 如何修补模型生成器中内置的 rails ?

ruby-on-rails - 返回 false,则无法将项目添加到 :through 的 has_many 中