Adding belongs to relationship to Ruby Gem Mailboxer

前端 未结 4 1961
情话喂你
情话喂你 2021-01-03 10:08

I am building an e-com application and would like to implement something like a messaging system. In the application, all conversation will be related to either a Prod

相关标签:
4条回答
  • 2021-01-03 10:11

    The gem automatically take care of this for you, as they have built a solution that any model in your own domain logic can act as a messagble object.

    Simply declaring

    acts_as_messagable
    

    In your Order or Product model will accomplish what you are looking for.

    0 讨论(0)
  • 2021-01-03 10:12

    I ended up customizing the Mailboxer gem to allow for a conversationable object to be attached to a conversation.

    In models/mailboxer/conversation.rb

    belongs_to :conversationable, polymorphic: true
    

    Add the migration to make polymorphic associations work:

    add_column :mailboxer_conversations, :conversationable_id, :integer
    add_column :mailboxer_conversations, :conversationable_type, :string
    

    In lib/mailboxer/models/messageable.rb you add the conversationable_object to the parameters for send_message:

    def send_message(recipients, msg_body, subject, sanitize_text=true, attachment=nil, message_timestamp = Time.now, conversationable_object=nil)
      convo = Mailboxer::ConversationBuilder.new({
        :subject    => subject,
        :conversationable => conversationable_object,
        :created_at => message_timestamp,
        :updated_at => message_timestamp
      }).build
    
      message = Mailboxer::MessageBuilder.new({
        :sender       => self,
        :conversation => convo,
        :recipients   => recipients,
        :body         => msg_body,
        :subject      => subject,
        :attachment   => attachment,
        :created_at   => message_timestamp,
        :updated_at   => message_timestamp
      }).build
    
      message.deliver false, sanitize_text
    end   
    

    Then you can have conversations around objects:

    class Pizza < ActiveRecord::Base
      has_many :conversations, as: :conversationable, class_name: "::Mailboxer::Conversation"    
      ...
    end
    
    class Photo < ActiveRecord::Base
      has_many :conversations, as: :conversationable, class_name: "::Mailboxer::Conversation"    
      ...
    end
    

    Assuming you have some users set up to message each other

    bob = User.find(1)
    joe = User.find(2)
    pizza = Pizza.create(:name => "Bacon and Garlic")
    
    bob.send_message(joe, "My Favorite", "Let's eat this", true, nil, Time.now, pizza)
    

    Now inside your Message View you can refer to the object:

    Pizza Name: <%= @message.conversation.conversationable.name %>
    
    0 讨论(0)
  • 2021-01-03 10:13

    You could just use something like:

    form_helper :products
    

    and add those fields to the message form

    but mailboxer comes with attachment functionality(carrierwave) included

    this might help if you need something like attachments in your messages:

    https://stackoverflow.com/a/12199364/1230075

    0 讨论(0)
  • 2021-01-03 10:24

    Although rewriting a custom Conversation system will be the best long-term solution providing the customization requirement (Like linking with other models for instance), to save some time at the moment I have implement the link with a ConversationLink Model. I hope it would be useful for anyone in the future who are at my position.

    Model: conversation_link.rb

    class ConversationLink < ActiveRecord::Base
      belongs_to :conversation
      belongs_to :linkingObject, polymorphic: true
    end
    

    then in each models I target to link with the conversation, I just add:

    has_many :conversation_link, as: :linkingObject
    

    This will only allow you to get the related conversation from the linking object, but the coding for reverse linking can be done via functions defined in a Module.

    This is not a perfect solution, but at least I do not need to monkey patch the gem...

    0 讨论(0)
提交回复
热议问题