rubyruby-1.9rhomobilerhodes

How to use a variable from one method to other in a same class in Ruby?


I am new to Ruby. I have the below code in my controller. Desired Behaviour:- I want to display the validation error string on 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 behavior:- There is a variable @vpinerr in create method. I want 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

Solution

  • 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.

    1. 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

    1. 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].