pwz2000
pwz2000

Reputation: 1395

Wrong attribute value getting passed to table

I just noticed in my database that inside the Receipts table it is not showing the proper recipient_id for the receiver_id column. I am working between the Questions, Conversations and Receipts table with the Mailboxer gem.

For example here's the issue:

A new entry in the Questions table appears with the

id 552, sender_id 1, and recipient_id 2.

2 new entrys is then made in the Receipts table that's associated with the Questions entry just created (creates 2 entrys by default, one for recipient and other for sender). The details for the

first entry is id 547 and receiver_id 552.

The second entry id is 548 and receiver_id 1.

As you can see for the first entry the receiver_id is being copied from the Questions table id. It should be transferring the Questions table recipient_id instead.

I have no idea at how to fix this.

Questions controller:

 def create
      @question = Question.new(params[:question])
      if @question.save
        @message = current_user.send_message(@question, @question.question, "You have a question from #{@question.sender_id}") 
        redirect_to :back, notice: 'Your question was saved successfully. Thanks!'
      else
        render :new, alert: 'Sorry. There was a problem saving your question.'
      end
    end
  end

Question model:

  acts_as_messageable

  attr_accessible :answer, :question, :sender_id, :recipient_id, :conversation_id
  belongs_to :user

  belongs_to :sender,:class_name => 'User',:foreign_key => 'sender_id'

  belongs_to :recipient,:class_name => 'User',:foreign_key => 'recipient_id'

  belongs_to :message

  belongs_to :conversation

show.html.slim:

center
  .message_div
    = form_for Question.new, class: 'question_form form-horizontal', role: 'form' do |f|
      .form-group
        = f.text_field :question, {:placeholder => 'Please add your question...',class:'form-control'}
      = f.hidden_field :sender_id, :value => current_user.id
      = f.hidden_field :recipient_id, :value => @user.id
      = f.submit 'Ask Question', class: 'btn btn-primary'

schema.rb:

create_table "receipts", force: true do |t|
    t.integer  "receiver_id"
    t.string   "receiver_type"
    t.integer  "notification_id",                            null: false
    t.boolean  "is_read",                    default: false
    t.boolean  "trashed",                    default: false
    t.boolean  "deleted",                    default: false
    t.string   "mailbox_type",    limit: 25
    t.datetime "created_at",                                 null: false
    t.datetime "updated_at",                                 null: false
  end

  add_index "receipts", ["notification_id"], name: "index_receipts_on_notification_id", using: :btree

  add_foreign_key "receipts", "notifications", name: "receipts_on_notification_id"

Log:

Started POST "/questions" for 127.0.0.1 at 2014-08-08 17:00:12 -0400
Processing by QuestionsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"nYOcY69oD6WcfNGEJcKGpyupA0CNbYnAJz0SQ+dKtEk=", "question"=>{"question"=>"Stack Overflow can you help me out?", "sender_id"=>"3", "recipient_id"=>"2"}, "commit"=>"Ask Question"}
  User Load (0.3ms)  SELECT `users`.* FROM `users` WHERE `users`.`auth_token` = 'HkI7Lm4fJYHHf5LHEcMtvA' LIMIT 1
   (0.2ms)  BEGIN
  SQL (0.3ms)  INSERT INTO `questions` (`created_at`, `question`, `recipient_id`, `sender_id`, `updated_at`) VALUES ('2014-08-08 21:00:12', 'Stack Overflow can you help me out?', 2, 3, '2014-08-08 21:00:12')
   (0.4ms)  COMMIT
  User Load (0.4ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 3 ORDER BY `users`.`id` ASC LIMIT 1
   (0.1ms)  BEGIN
  SQL (0.3ms)  INSERT INTO `conversations` (`created_at`, `subject`, `updated_at`) VALUES ('2014-08-08 21:00:12', 'You have a question from 3', '2014-08-08 21:00:12')
  SQL (0.3ms)  INSERT INTO `notifications` (`attachment`, `body`, `conversation_id`, `created_at`, `sender_id`, `sender_type`, `subject`, `type`, `updated_at`) VALUES (NULL, 'Stack Overflow can you help me out?', 419, '2014-08-08 21:00:12', 3, 'User', 'You have a question from 3', 'Message', '2014-08-08 21:00:12')
  SQL (0.3ms)  INSERT INTO `receipts` (`created_at`, `mailbox_type`, `notification_id`, `receiver_id`, `receiver_type`, `updated_at`) VALUES ('2014-08-08 21:00:12', 'inbox', 459, 577, 'Question', '2014-08-08 21:00:12')
   (0.4ms)  COMMIT
   (0.1ms)  BEGIN
  SQL (0.4ms)  INSERT INTO `receipts` (`created_at`, `is_read`, `mailbox_type`, `notification_id`, `receiver_id`, `receiver_type`, `updated_at`) VALUES ('2014-08-08 21:00:12', 1, 'sentbox', 459, 3, 'User', '2014-08-08 21:00:12')
   (0.4ms)  COMMIT
   (0.1ms)  BEGIN
   (0.1ms)  COMMIT
Redirected to http://localhost:3000/users/user
Completed 302 Found in 562ms (ActiveRecord: 62.3ms)

Upvotes: 0

Views: 199

Answers (1)

Marc Lainez
Marc Lainez

Reputation: 3080

When you call send_message in your controller, you pass @question as a recipient. It means that the first receipt is indeed built with the question_id as receiver_id. But from what I understand, you want the question's recipient to be sent the message. Simply replace your send_message call with:

current_user.send_message(@question.recipient, @question.question, "You have a question from #{@question.sender_id}") 

What's happening behind the scene

The Receipt table from mailboxer can be considered as a proof that a notification has been sent. In your model, by adding

acts_as_messageable

You include the Messageable module described in the mailboxer documentation, including the following send_message method:

def send_message(recipients, msg_body, subject, sanitize_text=true, attachment=nil, message_timestamp = Time.now)
  # message = ...
  # message building stuff happening

  message.deliver false, sanitize_text
end

When you call that method from your controller, it calls the deliver method on this newly created message. Here's the interesting bits of that method, extracted from the mailboxer documentation:

def deliver(reply = false, should_clean = true)
  # ... some stuff

  #Receiver receipts
  temp_receipts = recipients.map { |r| build_receipt(r, 'inbox') }

  #Sender receipt
  sender_receipt = build_receipt(sender, 'sentbox', true)

  temp_receipts << sender_receipt

  if temp_receipts.all?(&:save!)
    # some other stuff
  end
  sender_receipt
end

As you can see temp_receipts = recipients.map { |r| build_receipt(r, 'inbox') } builds a receipt for every recipient of the message.

The second interesting line sender_receipt = build_receipt(sender, 'sentbox', true) builds a receipt for the sender. Which in your case is the current_user.

Hope it helps.

Upvotes: 1

Related Questions