Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rails 4 with link_to and method post with strong parameters

I'm stuck in a problem which can't be that complicated, but I'm just not getting things right.

Assuming I've got two Models:

class Notification < ActiveRecord::Base
  belongs_to :device

  validates :number, presence: true
end

and

class Device < ActiveRecord::Base
  belongs_to :user
  has_many :notifications, :dependent => :destroy

  //rest omitted for brevity
end

with nested routes like so:

 resources :devices do
   resources :notifications
 end

and a notifications controller like so:

class NotificationsController < ApplicationController
  before_filter :authenticate_user!
  before_action :set_device, :only => [:index, :new, :create]
  before_filter :load_notification, only: :create

  load_and_authorize_resource :device
  load_and_authorize_resource :notification, :through => :device


  def index
  end

  def new
    @notification = @device.notifications.build
  end

  def create
    params.each do |param|
      logger.debug param
    end
    @notification = @device.notifications.build(notification_params)
    if @notification.save
      redirect_to [@notification.device, @notifications], notice: 'Notification was successfully created.'
    else
      render action: 'new'
    end
  end

  private

  def load_notification
    @notification = Notification.new(notification_params)
  end

  def set_device
    @device = Device.find(params[:device_id])
  end

  def notification_params
    params.fetch(:notification, {}).permit(:number, :device_id, :message)
  end
end

Now when it comes to create notifications: The Form works as aspected. BUT: I want to achieve a second goal. Notifications should be resendable, so I have this in notifications index view:

<%= link_to 'Resend', device_notifications_path(number: notification.number, message: notification.message), :method => :post %>

But the validation fails and im redirected to new page without any prefilled fields telling me that number is required, so there must be missing something obvious I don't get.

The params from the request:

[["user_id", xyz]]
["_method", "post"]
["authenticity_token", "myauthenticitytokenstring"]
["number", "+1555123456789"]
["action", "create"]
["controller", "notifications"]
["device_id", "9"]
["notification", {}]

(Message is not required)

I think the error lies in my notification_params method in the controller.

Can anyone help me, please?

like image 468
Julian Kaffke Avatar asked Aug 15 '13 07:08

Julian Kaffke


1 Answers

I had a similar problem just now, and this is what worked for me:

<%= link_to 'Resend', device_notifications_path(@notification.device_id, notification: { number: notification.number, message: notification.message }), :method => :post %>

Basically, you need to wrap your controller/model data into a hash for the controller's params. That's just how the controller itself reads it. Also, are you not missing the device_id in your device_notifications_path ?

[["user_id", xyz]]
["_method", "post"]
["authenticity_token", "myauthenticitytokenstring"]    
["action", "create"]
["controller", "notifications"]
["device_id", "9"]
["notification", {["number", "+1555123456789"]}]

Now, in saying that, I'm just assuming that device_id is located in your URL route: http:\\localhost:3000\notifications\9

This is why device_id would not have to be in the hash itself. This is just based on what I'm assuming here without more of the view and routes to go on. All in all, it does have to do with the hash. Play around a bit, and use p to print out data in your development.log to test:

def create
  p params
  p notification_params

  ...
end

In addition, optional but not required, you could DRY up your controller's params def using .require instead of .fetch like this:

private

def notification_params
  params.require(:notification).permit(:number, :device_id, :message)
end
like image 63
Eric Wanchic Avatar answered Nov 15 '22 10:11

Eric Wanchic