Tyrel Denison
Tyrel Denison

Reputation: 476

How do I pass a parameter from my new method to my create method in Rails?

I am needing to call a method at the end of my create method if a specific parameter has been passed to the new method. I'm trying to do this without adding a new field to the object I am creating, solely for the purpose of being a temporary "parameter bucket". The parameter won't be used in the creation of the new object, but in the secondary method called after the object is saved.

So in code something like...

def new
  @object = Object.new
  if params[:object_id]
    @object_trade = Object.find(params[:object_id])
  end
end

def create
  blah create blah
  if @object.save && @object_trade.present?
    call_method_here(@object_trade.id)
  end
end

I can't quite put the pieces together though. I feel like I'm missing something obvious.

For what it's worth, i could pass the object or just a parameter for what I am needing to do.

Any help is appreciated.

Upvotes: 1

Views: 1888

Answers (2)

antinome
antinome

Reputation: 3458

Kirti Thorat rightly points out why an instance variable won't work, but suggests using the session, which is potentially buggy.

What if the user navigates to the 'new' page with an object_id, but never submits the form? Instead they hit the back button and make another request to 'new', this time without object_id, because they changed their mind. However, object_trace is still hanging around in the session and the app wrongly remembers the original object_id.

I believe flash would be subject to similar problems.

Avoiding the session is easy

Render a hidden field in the form that your 'new' action renders:

= hidden_field_tag 'object_id', params[:object_id]

Then, when you submit the form, the object_id will be passed, and will be available to the create action as params[:object_id].

Additional reasons to avoid the session

  • Easier to understand and debug: as your application gets more complicated, you will find it is much simpler if a bug that happens in a request happens every time you run the same request with the same parameters. It is no fun trying to fix a bug that you can't reliably reproduce.
  • The stateless approach is just as easy to implement as the stateful approach
  • Avoid the limitations of whatever type of session storage your app is configured to use:
    • If using cookie storage, you'll eventually want to store something that's too big to fit in a cookie.
    • If using database storage, you may someday run into issues where values are hanging around in the session indefinitely.
    • If using memcache storage, you will not be able to scale your app to more than one memcached instance, and also your app will break any time you need to restart memcached (or the server it's on).

Upvotes: 2

Kirti Thorat
Kirti Thorat

Reputation: 53018

Redefine your methods as below:

def new
  @object = Object.new
  if params[:object_id]
    session[:object_trade] = params[:object_id]
  end
end

def create
  blah create blah
  if @object.save && session[:object_trade].present?
     @object_trade = Object.find(session[:object_trade])
     call_method_here(@object_trade.id)
     session.delete(:object_trade)  ## Remove object_trade from the session
  end
end

Every time you call an action a separate instance of your controller is loaded. Hence, you would not get the @object_trade in create action. BUT session will allow you to share the data between different actions.

NOTE:

The reason to remove object_trade from the session, i.e., session.delete(:object_trade) is at a given time only one new action can be performed per session. This way the concern raised by antinome (in comments) would not perform activities in if block of create action. If OP wants to give user a message then he could just add a flash message in else part stating the reason something like session key invalid..Please try again and redirect to new form.

Upvotes: 2

Related Questions