2

NOTE: This question has been answered (by me), and the information below turned out to be a red herring. I leave it here in case it helps someone. See below for the answer!

I'm upgrading all of my controllers to strong parameters, and I'm running into problems with an API controller where I have to do some funky timezone stuff.

The strong paramaters are deal_strong_params, and the problem seems to come with having them as the second argument in the deal_params line. I've tried a ton of things, like playing around with that ActionController::Parameters.new() thing, but that hasn't done it. As is often the case with strong parameters, I'm getting 400 errors instead of my expected responses. I've tried SO many things, and I really welcome your suggestions.

Relevant code from the API controller:

before_filter :validate_update_params, :only => [:update]
.
. [show method left out]
.
def update
 deal = SuperDeal.find_by_id(params[:id])
 return head :not_found unless deal

 deal_params = convert_time_to_local(deal, deal_strong_params)

 respond_to do |format|
  format.json {
    if deal.update_attributes(deal_params)
      render :text => "Successful update", :status => :created
    else
      render :text => "Unsuccessful update: # {deal.errors.full_messages.join(", ")}", :status => :expectation_failed
     end
   }
 end
end

The strong params:

def deal_strong_params
 params.require(:deal).permit(:offer_starts_at,:offer_ends_at,:copy_complete,:short_title, { :deal_status_attributes => [:id, :ops_complete_at] })
end

And the special time formula that works with TimeCop. I include it since I need it:

def convert_time_to_local(deal, deal_params)
 # times are coming in as UTC
 [:offer_starts_at, :offer_ends_at].each do |attribute|
   next unless deal_params[attribute]
   deal_params[attribute] = deal.timezone.parse("#{deal_params[attribute]} UTC")
 end
 deal_params
end
wisetara
  • 95
  • 1
  • 10

1 Answers1

0

UPDATE WITH ANSWER: It turns out I didn't include what was the key to finding the answer. THE PROBLEM WAS IN THE TESTS. These particular tests were to make sure that a deal could NOT be updated.

Without strong parameters, one can write a test that passed in an empty hash of parameters to update, which would work fine if you're just testing that it doesn't update, as long as you're passing in a separate id to test (though in hindsight, it's probably good to have something in there just to make sure).

ActionController::TestCase BEFORE:

should "return not found if it can't find the deal" do
  put :update, :id => 0, :deal => {}
  assert_response :not_found
end

With strong parameters, one MUST include something in that hash. Just stick one of the attributes in there with at least one attribute. This actually makes it a more robust test, passing in more than the ID, but moreover (as I discovered), it's required with strong parameters. I haven't found this documented anywhere, and I hope it helps someone someday that I'm leaving it here.

ActionController::TestCase AFTER:

should "return not found if it can't find the deal" do
  put :update, :id => 0, :deal => { :copy_complete => true } #NOTE: Strong params doesn't allow an empty :deal => {}
  assert_response :not_found
end
wisetara
  • 95
  • 1
  • 10