linking to the product from the index in rails - ruby-on-rails

When I save a PayerContract in the create form, it saves the PayerContract and creates a "success you have created PayerContract {X}" where {X} is the PayerContract name and redirects the user back to the index. I want to allow the user to click the {X} to go to the edit page for that PayerContract.
In my index page I have:
= link_to t('payer_contracts.edit'), edit_payer_contract_path())
I need to give the PayerContract.id to the edit_payer_contract_path function. So, it would look something like edit_payer_contract_path(330)
The warning message I have displayed in my controller is this:
def create
payer_contract_params = PayerContract.assign_params_to_payer_contract(params)
#payer_contract = PayerContract.new(payer_contract_params)
respond_to do |format|
begin
if #payer_contract.save
format.html { redirect_to payer_contracts_path, notice: t('common.successfully_created', entity: #payer_contract.description) }
end
end
end
end
I found out that when I do something like:
edit_payer_contract_path(PayerContract.find()) it returns all the PayerContract that looks like: expected an attributes Hash, got [{"id"=>224, "name" ="hello", "id"=> 332, "name" = "hello2", "id"=>555, "name" = "sup" }] etc.
How can I correctly link the user to the PayerContract they just created?

you can have it two ways. Either pass parameter along your redirect_to method. obviously, pass the id of newly created PayerContract. This way you will have the id in params and you can use it in your link_to method.
If you don't want to pass the parameter, try storing the newly created PayerContract in session after successfully creating PayerContract. This way after redirect you will still have access to the saved value from the session
something like below
def create
#foo = Foo.new(foo_params)
if foo.save
session[:foo_id] = #foo.id
redirect_to foo_path
end
end

As beniutek said you can pass parameter in redirect_to. But when user first visit index page id is not defined so you can check in view if it is define set the id to link_to as below.
def create
payer_contract_params = PayerContract.assign_params_to_payer_contract(params)
#payer_contract = PayerContract.new(payer_contract_params)
respond_to do |format|
begin
if #payer_contract.save
format.html { redirect_to payer_contracts_path(id: #payer_contract.id), notice: t('common.successfully_created', entity: #payer_contract.description) }
end
end
end
end
In view
if params[:id].present?
= link_to t('payer_contracts.edit'), edit_payer_contract_path(params[:id].to_i))

Related

Send a variable from one action to another in ruby on rails

Code in controller is
if params["type"] == "user"
respond_to do |format|
format.html { redirect_to home_user_path, notice: "abc" }
end
If I send variable with notice then work fine but I want to send with my own key like
format.html { redirect_to home_user_path, search: "abc" }
It doesn't recieve there
You must remember that you're not "sending" a variable to another action; you're invoking another action, and populating it with a variable (data):
1. Instance Variable
You can set an instance variable, which will then be available in the next action:
def your_action
#search = "abc"
respond_to do |format|
format.html { redirect_to home_user_path } #-> #search will be available in the other view
end
end
2. Sessions
You're currently trying to use sessions to populate the data:
def your_action
redirect_to home_user_path, search: "abc"
end
#app/views/controller/your_action.html.erb
<%= flash[:search] %>
3. URL
Finally, you can set the value in the URL through your routes:
def your_action
redirect_to home_user_path(search: "abc") #-> you'll probably need to set the user object too, judging from the route name
end
This should populate your route with some GET request params: url.com/action?param=value
The underpin of all of this, as mentioned, is that you're not sending a variable, you'll be initializing it in your current controller action, and then having the next action call it.
This is a problem with Ruby's optional braces: sometimes it's hard to see which method call something is being treated as an argument to.
Try this instead:
format.html { redirect_to home_user_path(search: "abc") }
this will redirect to home_user_path and set params[:search] to "abc".

Rails controller redirect to form in another controller then back to saved model

I need to do something kind of weird in my Rails app. Once a user creates a Product instance through the create action, I need it to save and then redirect them to a Braintree payment method form if they haven't already added one to their account, and only then redirect them to the show page for the product.
Here's the product create action:
def create
#product = Product.new(product_params)
#product.set_user!(current_user)
if #product.save
if !current_user.braintree_customer_id?
redirect_to "/customer/new"
else
redirect_to view_item_path(#product.id)
end
else
flash.now[:alert] = "Woops, looks like something went wrong."
format.html {render :action => "new"}
end
end
The confirm method for the Braintree customer controller is this:
def confirm
#result = Braintree::TransparentRedirect.confirm(request.query_string)
if #result.success?
current_user.braintree_customer_id = #result.customer.id
current_user.customer_added = true
current_user.first_name = #result.customer.first_name
current_user.last_name = #result.customer.last_name
current_user.save!
redirect_to ## not sure what to put here
elsif current_user.has_payment_info?
current_user.with_braintree_data!
_set_customer_edit_tr_data
render :action => "edit"
else
_set_customer_new_tr_data
render :action => "new"
end
end
Is what I want to do possible?
You can store product id in a session variable before redirecting to braintree form, a then after complete confirmation just read this id from session and redirect to product show action.
if !current_user.braintree_customer_id?
session[:stored_product_id] = #product.id
redirect_to "/customer/new"
else
redirect_to view_item_path(#product.id)
end
Keep in mind that user can open product view page just by entering valid url address if he knows product id, so you should also handle this kind of situation. You can put before_filter in product show action to check if user has brain tree setup. If you go this way, you don't need to have condition in create action. You can always redirect to product show page and before_filter will check if user needs to update braintree data.

invitation type field values is not set in Ror form using session hascode..shows invalid type in ror form

I have created a form where a form is saved using the hash-code generated form an invitation table:
class VectorsController < ApplicationController
def create
ui = UserInvitation.where(hash_code: session[:hash_code]).first
#vendor = Vendor.new(vendor_params.merge({user_id: current_user.id, vendor_type: ui.try(:invitation_type)}))
respond_to do |format|
if #vendor.save
ui.completed_registration = true
ui.save
session[:hash_code] = nil
flash[:notice] = "You're all set! Welcome to Availendar!"
format.html {redirect_to vendor_path(#vendor.id)}
else
flash[:alert] = "Oops, looks like there's been a problem. Please correct it and try again."
format.html {render action: :invited_new}
end
end
end
the form claims that vendor_type is not valid - but in the UserInvitation table the values are already set in invitation_type field, yet it shows no value for vendor_type...
What could be the reason? Is it due to session? I just want to set the invitation_type from the UserInvitation table to be stored as vendor_type value in vector controller /create action. How to set the value?

Instantiate instance variable in helper method from controller

I have a helper which instantiates a model and renders a form. This form should be available to any view in the application
# support_form_helper
def support_form
#support_stats = SupportForm::Stat.find(get_stats_id)
#enquiry = SupportForm::Enquiry.new(stats_id: #support_stats.id)
render partial: 'support_form/enquiries/form'
end
And its rendered in the view:
# some_view.html.erb
<%= support_form %>
This is fine until I want to submit the form and validate it in the controller.
# enquiries_controller.rb
def create
#enquiry = SupportForm::Enquiry.new(params[:support_form_enquiry])
topic = #enquiry.topic
#stat = SupportForm::Stat.find(#enquiry.stats_id)
#stat.stats[topic] = #stat.stats[topic].to_i.next
respond_to do |format|
if #enquiry.valid? && #stat.save
format.html { redirect_to(root_path) }
else
format.html { redirect_to(:back) }
end
end
end
This is where I can't render the previous view with the errors attached to the invalid object. The helper gets invoked again and initializes a new #enquiries object, without the errors obviously.
How can I render the form in many views across an application and still return to the view with the object together with errors when it is invalid?
I found an answer which answers my question but its a bad idea:
Render the action that initiated update
def create
#enquiry = SupportForm::Enquiry.new(params[:support_form_enquiry])
topic = #enquiry.topic
#stat = SupportForm::Stat.find(#enquiry.stats_id)
#stat.stats[topic] = #stat.stats[topic].to_i.next
if #enquiry.valid? && #stat.save
redirect_to(root_path)
else
render Rails.application.routes.recognize_path(request.referer).values.join("/")
end
end
The problem is that there will likely be instance variables in the view that submitted the form and I would have to be able to instantiate all the instance variable in the application then.....not possible.
Currently I'm considering putting the errors in the flash hash... not something I want to do. With the original object returned i can repopulate the fields with the users input.
When you use redirect_to, rails will kick off a whole new controller & view sequence. Use
render "path/to/template/from/view/folder"`
instead.
A typical create action using this pattern would look like (for a 'post' object in this case):
def create
#post = Post.new(params[:post])
#created = #post.save
respond_to do |format|
if #created
flash[:notice] = 'Post was successfully created.'
format.html { redirect_to post_path(#post) }
format.js
else
format.html { render :action => :new }
format.js
end
end
end
Notice how if it's successfully created we do a full redirect to the "show" page for the post, but if it's not successful we just do a render.
You should probably modify your support_form helper so that it only creates a new #enquiry if it hasn't been created already:
def support_form
#support_stats = SupportForm::Stat.find(get_stats_id)
#enquiry ||= SupportForm::Enquiry.new(stats_id: #support_stats.id)
render partial: 'support_form/enquiries/form'
end
||= is shorthand for "equals itself or". If it hasn't been defined (or is nil or false) then it will fail the first part of the or and pass through to the second, where the object is created.
In your form partial, also, you should make sure you're using form_for, which will submit to the create or update action depending on whether the object has been saved already.

Check if record exists in Rails controller

I want to check if the entry with the id 2 exists in the settings table and if not i want that the user gets redirected to the setting_new_path. My code looks like this:
def index
if Setting.find(2).present?
#patients = Patient.all
#patients_drucken = Patient.drucken
#anrede = Setting.find(1).anrede
respond_to do |format|
format.html # index.html.erb
format.json { render json: #patients }
end
else
redirect_to new_setting_path
end
end
But somehow i get the error:
Couldn't find Setting with id=2
I dont get why this is displayed as an error! I mean in the case its not defined i worte , redirect to new_setting_path! What made i wrong?
Use exists? to check for record presence:
if Setting.exists?(2)
#find will throws an exception if the record is not found.
You should use #where and #any? instead :
if Setting.where( id: 2 ).any?
It means you don't have any record with id = 2 in Settings table. Just check it once.

Resources