Why is code inside model running without being asked, and how to run it on link click only?

I have this link in the view:

      <%= link_to "Pay in PayPal", @order.paypal_url(edit_order_url,
payment_notification_url), class: "btn btn-success" %>

And this in the model:

     class Order < ActiveRecord::Base
     def paypal_url(return_url, notify_url)
        # ... Do stuff
        self.update_attribute(:payment_in_process, true)
        # Do more stuff...
      end

When I visit the view, the model gets its attribute updated. I do not
want this. I only want the attribute updated if the link is clicked.

Know how to accomplish this?

Hi

nanaya wrote in post #1183942:

Hi

     class Order < ActiveRecord::Base
     def paypal_url(return_url, notify_url)
        # ... Do stuff
        self.update_attribute(:payment_in_process, true)
        # Do more stuff...
      end

When I visit the view, the model gets its attribute updated. I do not
want this. I only want the attribute updated if the link is clicked.

You call the method in the view, thus the method is run. Nothing more,
nothing less.

Nanaya, what can I do to only update the attribute when the link is
clicked?

Separate out the code that generates the url from the code that
updates the database. Then run the update in the action that is
called when the link is clicked.

Colin

Colin Law wrote in post #1183944:

Colin Law wrote in post #1183944:

     class Order < ActiveRecord::Base
     def paypal_url(return_url, notify_url)
        # ... Do stuff
        self.update_attribute(:payment_in_process, true)
        # Do more stuff...
      end

When I visit the view, the model gets its attribute updated. I do not
want this. I only want the attribute updated if the link is clicked.

Know how to accomplish this?

Separate out the code that generates the url from the code that
updates the database. Then run the update in the action that is
called when the link is clicked.

Colin

Colin, there's no action called when the link is clicked, it just
follows the URL generated by the method.

Well that is what you need to fix. If you need to do something to the
database then you need to call an action in your application that does
whatever it is you want to do. If necessary you can then redirect to
your external url.

Are you a beginner with Rails? If so then I suggest that before going
further you work right through a good tutorial such as
railstutorial.org (which is free to use online), that will show you
the basics of Rails.

Colin

Colin Law wrote in post #1183946:

want this. I only want the attribute updated if the link is clicked.

follows the URL generated by the method.

Well that is what you need to fix. If you need to do something to the
database then you need to call an action in your application that does
whatever it is you want to do. If necessary you can then redirect to
your external url.

Are you a beginner with Rails? If so then I suggest that before going
further you work right through a good tutorial such as
railstutorial.org (which is free to use online), that will show you
the basics of Rails.

Colin

Managed to solve this a while ago :slight_smile:

I created an action for the link which generates and follows the link,
then when it gets back from it (PayPal), it updates the database.

  post 'orders/:id/pay', to: 'orders#start_payment_process', as:
'start_payment_process'

    <%= link_to "Pagar en PayPal", start_payment_process_path, class:
"btn btn-success", method: :post %>

  def start_payment_process
    @order = current_order
    @order.update_attribute(:payment_in_process, true)
    redirect_to @order.paypal_url(edit_order_url,
payment_notification_url)
  end

  def edit
    # ... Some code
    if @order.payment_notifications.any? && @order.payment_in_process
      @order.update_attribute(:payment_in_process, false)
    end
  end

Thanks!