这些实例变量相互重写有什么问题?

时间:2011-08-07 15:45:52

标签: ruby-on-rails instance-variables

这让我发疯了......这就是我在我的users_controller.rb的#show动作中所做的事情

  1. 我只通过方法“pass_session_data()”设置会话[:zot]。
  2. 在该方法中,我将“@foo”的内容传递给会话[:zot]。
  3. 稍后在#show操作中,我调用了amz_search(),并将@ nowreading.content中的一些文本替换为一个URL和该文本。
  4. 在调用方法“amz_search()”之后,所有投注均已关闭。当我输入“test 4”时,我看到会话[:zot]已更改为包含我添加到@ nowreading.content的URL。更糟糕的是,当我改变@ nowreading.content时,我的变量@foo也发生了变化。 WTF。我不明白这两个变量是如何联系在一起的!

    我做错了什么?我想将未经改动的文本(@foo在更改为带URL的版本之前)传递给会话[:zot]。

    在Users控制器的show动作中,我有:

    @user = User.find(params[:id])
    @nowpost = Nowpost.new
    
    @tweet_sample = Micropost.find(:all, :conditions => ["username = ?", "#{@user.twithandle}"])
    
    @multi_streams = (@tweet_sample + @user.nowposts).sort_by(&:updated_at)
    # takes all posts in the systems and order them by update-time
    
    parse_the_streams(@multi_streams) 
    
    pass_session_data() 
    
     puts "test 3"
     puts session[:zot]
     puts "this is @foo = #{@foo.content}"
     puts "Test C = #{@nowreading_raw.content}"   
    
    amz_search(@reading_title, 'Books')
    
     puts "test 4"
     puts session[:zot]
     puts "this is @foo = #{@foo.content}"
     # @foo totally changed even though I only updated @nowpost.content
     # I don't understand how these two variables are linked!
     puts "Test D = #{@nowreading_raw.content}"   
    
     end #show action
    

    以下是show action的调用方法:

     def parse_the_streams(multi_streams)
         multi_streams.each do |tweet, i|  
     puts "i = #{i} // tweet = #{tweet.content}"
           if tweet.content.match(/#nowreading/).to_s == "#nowreading"    
             @nowreading_raw = tweet 
             @foo = tweet
             tweet.update_attributes(:cat_id => "1")
    
            if tweet.content.match(/#nowreading$/)
              @reading_title = tweet.content.match(/([^\s]*\s){5}(#nowreading$)/).to_s
            else
              @reading_title = tweet.content.match(/'(.+)'|"(.+)"/).to_s
            end              
         end
       end
     end
    
     def pass_session_data  
          @nowreading = @nowreading_raw
          puts "PASS SESSION DATA"
          puts "this is @foo = #{@foo.content}"
          puts "----------"
          reading = @foo
    
          content = {
          "reading"=>reading
          }
    
          session[:zot] = content
        end
    
      def amz_search(search, index)
            res = Amazon::Ecs.item_search(search, {:response_group => 'Images', :search_index => index})
            puts "Test 1 = #{session[:zot]["reading"].content}" 
    
            tempy = @nowreading.content.match(/#nowreading.*/).to_s.gsub("#nowreading",'') # strips away the #nowreading tag
    
            puts "Test 2 = #{session[:zot]["reading"].content} -- this is still OK"   
            puts "and FOO hasn't changed yet = #{@foo.content}"   
    
            url = create_amz_url(search, asin)["finished"]
    
            @nowreading.content = tempy.match(/#{search}.*/).to_s.gsub("#{search}", url)
    
            puts "WTF -- @foo changed -- WHY!?!? = #{@foo.content}"   
            puts "Test 4 = #{session[:zot]["reading"].content}"
      end
    
      def create_amz_url(text, asin)
         url = Hash.new
         url["raw"] = "http://www.amazon.com/dp/#{asin}/#{associate_code}"
         link = "http://www.amazon.com/dp/#{asin}/#{associate_code}"
         url["finished"] = "<a href=#{link} target=\"_blank\">#{text}</a>"
         return url
      end
    

    感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

您应该花30分钟重构该代码 - 尽可能多地消除实例变量,并使用函数的显式参数,而不是对实例变量进行操作。

我很确定您的问题是

@foo == @nowreading == @nowreading_raw
session[:zot] = {"reading" => @foo}

然后在 WTF 语句之前更改@nowreading

tweet是一个对象,因此当您说@foo=tweet; @nowreading=tweet时,@foo@nowreading指向同一个对象,而修改其中任何一个都会修改它们。