问题
I am new to Ruby. I have a below code in my controller. Desired Behaviour :- I want to display validation error string to my views on edit page. So I am putting those errors in a variable. When validation fails then I want to use that variable in my edit method, so that I can display that on my edit page view.
Observed behaviour :- There is a variable @vpinerr in create method. I wan to use that variable in edit method. I have tried to use the class variable (@@vpinerr) and initialized it with an empty string (@@vpinerr = "") then the value of this variable becomes empty in edit method.
require 'rho/rhocontroller'
require 'helpers/browser_helper'
class LeadController < Rho::RhoController
include BrowserHelper
# GET /Lead
def index
@leads = Lead.find(:all)
render :back => '/app'
end
# GET /Lead/new
def new
@lead = Lead.new
render :action => :new, :back => url_for(:action => :index)
end
def create
# Update
if Lead.find(@params['id'])
@lead = Lead.find(@params['id'])
# array of objects
@leadadd = LeadAddress.find(:all,
:conditions => {:parentKey => @lead.object}
)
@leadcon = LeadContact.find(:all,
:conditions => {:parentKey => @lead.object}
)
#hash of hashes
leadaddressArray = @params['leadaddress']
arr1 = @leadadd.count - 1
for i in 0..arr1
j=i.to_s
@leadaddHash = @leadadd[i]
leadaddressHash = leadaddressArray[j]
if leadaddressHash['removed'] == "1"
singleadd = LeadAddress.find(:first,
:conditions => {:object => leadaddressHash['object']}
)
singleadd.destroy if singleadd
else
#validation
vpin = leadaddressHash['pincode']
#validation check
if vpin =~ /^[[:digit:]]+$/
@leadaddHash.update_attributes(leadaddressHash) if @leadaddHash
else
err = 1
@vpinerr = "Pincode is invalid"
end
end
end
leadconArray = @params['leadcontact']
arr2 = @leadcon.count - 1
for k in 0..arr2
z=k.to_s
@leadconHash = @leadcon[k]
leadContact = leadconArray[z]
if leadContact['removed'] == "1"
singlecon = LeadContact.find(:first,
:conditions => {:object => leadContact['object']}
)
singlecon.destroy if singlecon
else
@leadconHash.update_attributes(leadContact) if @leadconHash
end
end
@lead.update_attributes(@params['lead']) if @lead
if err == 0
redirect :action => :index
else
redirect :action => :edit, :id => @lead.object, :vpin =>@vpinerr
end
else
# Create
err = 0
# validation
vlead = @params['lead']
vfirstname = vlead['firstname']
vlastname = vlead['lastname']
vage = vlead['age']
#validation check
if (vfirstname =~ /^[[:alpha:][:blank:]]+$/) and (vlastname =~ /^[[:alpha:][:blank:]]+$/) and (vage =~ /^[[:digit:]]+$/)
@lead = Lead.create(@params['lead'])
@key = @lead.object
else
err = 1
@basicerr = "Basic Details are invalid"
end
if @params['leadaddress']
leadaddressArray = @params['leadaddress']
arrcount = leadaddressArray.count
for i in 1..arrcount
j=(i-1).to_s
leadaddressHash = leadaddressArray[j]
#validation
vpin = leadaddressHash['pincode']
#validation check
if vpin =~ /^[[:digit:]]+$/
@leadAdd = LeadAddress.create(leadaddressHash)
@leadAdd.parentKey = @key
@leadAdd.save()
else
err = 1
@vpinerr = "Pincode is invalid"
end
end
end
if @params['leadcontact']
leadconArray = @params['leadcontact']
arrcount2 = leadconArray.count
for k in 1..arrcount2
h=(k-1).to_s
leadconHash = leadconArray[h]
#validation
vhome = leadconHash['home']
vmobile = leadconHash['mobile']
vemail = leadconHash['email']
#validation check
if (vhome =~ /^[[:digit:]]+$/) and (vmobile =~ /^[[:digit:]]+$/) and (vemail =~ /\A([\w+\-]\.?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i)
@leadcontact = LeadContact.create(leadconHash)
@leadcontact.parentKey = @key
@leadcontact.save()
else
err = 1
@contacterr = "Contact Details are invalid"
end
end
end
if err == 0
redirect :action => :index
else
redirect :action => :edit, :id => @lead.object
end
end
end
# GET /Lead/{1}
def show
@lead = Lead.find(@params['id'])
@leadadd = LeadAddress.find(:all,
:conditions => {:parentKey => @lead.object}
)
@leadcontact = LeadContact.find(:all,
:conditions => {:parentKey => @lead.object}
)
if @lead
render :action => :show, :back => url_for(:action => :index)
else
redirect :action => :index
end
end
# GET /Lead/{1}/edit
def edit
@lead = Lead.find(@params['id'])
@leadaddress = LeadAddress.find(:all,
:conditions => {:parentKey => @lead.object}
)
@leadcontact = LeadContact.find(:all,
:conditions => {:parentKey => @lead.object}
)
@vpinerr2 = @vpinerr
if @lead
render :action => :new, :back => url_for(:action => :index)
else
redirect :action => :index
end
end
end
回答1:
Variables with a prepending @
are considered as instance variables and are available in a class's instance. Your controller is a class and with every request, Rails instantiates a new controller instance. In that sense, when you make a request to the create action, a new instance is created and @vpinerr
is set in the instance. When you redirect the user to the edit action, its a new request and a new controller instance is instantiated. Since the instances from create action and edit actions are different, you won't have the value of @vpinerr
in the edit action.
You have alternatives.
- Class-level variables.
Class-level variables are set on the class and are available in all instances. Any variable prepended with @@
are class variables. Change to @@vpinerr
everywhere instead of @vpinerr
.
This would be wrong to use in your case because, you could want it to be different for each user but using class variable will keep the value for other users too until its changed. Read about class variables: http://www.railstips.org/blog/archives/2006/11/18/class-and-instance-variables-in-ruby
- Session variables.
Session variables are used to save variables within a session. They can be shared between controllers too. To set a session variable session[:vpinerr] = "Some error"
and to use it, you can simple call session[:vpinerr]
.
来源:https://stackoverflow.com/questions/44919066/how-to-use-a-variable-from-one-method-to-other-in-a-same-class-in-ruby