红宝石在轨道上

我是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在我的对话表单中包含一条消息,但由于我没有保存在我的数据库中的任何东西,所以我似乎无法将消息链接到一个未知的参与者。

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

要达到这个目标,正确的方法是什么? 我甚至在良好的轨道上,或者我应该改变一些东西或添加一些东西?

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


首先 ,为了让您的形式使用,接受嵌套属性fields_for形式帮手,你需要指定accepts_nested_attributes_for您的Conversation模式:

module Messenger
  class Conversation <ActiveRecord::Base

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

    # Required for form helper
    accepts_nested_attributes_for :participants

    [...]

既然您想要从同一表单中保存Participant及其Message ,则需要在Participant模型中添加第二个accepts_nested_attributes_for

module Messenger

  class Participant <ActiveRecord::Base

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

    # Required for form helper
    accepts_nested_attributes_for :messages

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

  end
end

接下来 ,在您的控制器中,由于这是一个新的Conversation ,最初没有任何Participant ,因此您需要build一个关联的Participant (可能基于current_user )以及此新Participant的关联Message

def new
  @conversation.participants.build(user: current_user).messages.build
end

最后在你的视图中,在三个嵌套块中指定属性字段, form_for @conversation do |f|f.fields_for :participants do |p| ,和p.fields_for :messages do |m|

= form_for @conversation, url: messenger.conversations_create_path do |f|
  [...]
  = f.fields_for :participants do |p|
    = p.fields_for :messages 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'

注意: Conversation的(错误实现的) messages方法应该用一个简单的has_many :through关系代替:

has_many :messages, through: :participants

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

所以完成之后,您可以使用在控制器中构建对话的默认消息

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

这很罗嗦,所以你可以添加一些模型方法来减少控制器调用

@conversation.build_default_message

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

class Conversation
  accepts_nested_attributes_for :messages
end

这将允许您使用1个或多个关联的消息创建对话

Conversation.create(
  ..., 
  messages_attributes: [
    { participant_id: 1, content: 'question' } 
  ]
)

首先,我认为,你在这种方法中有错误:

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

Conversation has_many :participants

self.participants将返回一个数组,而不是一个Participant活动记录对象。 所以你不能直接在数组上调用messages 。 您需要迭代该数组并在每个对象上调用messages

使用嵌套形式和fields_for方法和accepts_nested_attributes_for (你可以找到如何从SO或文档编写这些),并张贴代码代码和错误你得到了什么。 然后有人可能会帮助你。

并使用fields_for

由于无法直接链接的消息的Conversation ,你需要一个消息字段,你需要一个链接@message任何参与者。 您可以从current_user或第一个用户构建Participant ,例如@conversation User.first ,然后为此Participant构建@message

链接地址: http://www.djcxy.com/p/38167.html

上一篇: ruby on rails

下一篇: container with 100% height of section