что не так с этими переменными экземпляра, переписывающими друг друга? - PullRequest
0 голосов
/ 07 августа 2011

Это сводит меня с ума ... Вот что я думаю, я делаю в действии #show моего users_controller.rb

  1. Я устанавливаю сессию [: zot] ТОЛЬКО через метод "pass_session_data ()".
  2. В этом методе я передаю содержимое "@foo" сеансу [: zot].
  3. Позже в действии #show я вызываю amz_search () и заменяю некоторый текст в @ nowreading.content на URL и этот текст.

После вызова метода "amz_search ()" все ставки отключены. Когда я добавляю «test 4», я вижу, что сессия [: zot] изменилась, чтобы включить URL, который я добавил в @ nowreading.content. Хуже того, моя переменная @foo также изменилась, когда я изменил @ nowreading.content. WTF. Я не понимаю, как эти две переменные связаны!

Что я делаю не так? Я хочу передать неизмененный текст (@foo, прежде чем он изменится на версию с URL), в сеанс [: zot].

В действии show контроллера Users у меня есть:

@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:

 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 Ответ

1 голос
/ 07 августа 2011

Вы должны потратить 30 минут на рефакторинг этого кода - исключить как можно больше переменных экземпляра и использовать явные аргументы для ваших функций, а не работать с переменными экземпляра.

Я почти уверен, что ваша проблема в том, что

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

, а затем вы меняете @nowreading прямо перед вашим WTF заявлением.

tweet является объектом, поэтому, когда вы говорите, @foo=tweet; @nowreading=tweet, @foo и @nowreading указывают на один и тот же объект, и изменение любого из них изменит оба.

...