user2582234
user2582234

Reputation: 25

rails variables in production environment

I am developing a rails app. Most of the parts work fine, but I got one weird problem when I tried to calculate the time an user used to edit and submit one form.

I thought it would be good to do it in the following order: 1. in the controller "edit" method, record the time the user start to see the form. 2. in the "update" method, record the submit time, then do the math and get how long the user had spent on the form.

class Test
  @@start_time = 0
  @@end_time = 0

  def edit
    @@start_time = Time.now
  end

  def update
    @@end_time = Time.now
    time_used = @@end_time - @@start_time
    puts time_used.to_i
  end
end

The code above actually works fine while running on my own developing computer, the output is what I expected. But when I upload the code to the production environment(multicore cpus), sometime the output is right, sometime it is not. I debugged the code and found in some case, the @@start_time is set to 0 when submitting the form. I am confused what was going on, maybe I just misused the @@ for the variable. Please help me out, any idea would be appreciated, thanks.

Edit: The problem is solved by adding a virtual attribute to the model as hinted by Vishal. In addition, I added a hidden field in the submit form, and in the strong parameter part added the corresponding parameter to allow it to be passed from edit to update method.

Upvotes: 0

Views: 64

Answers (2)

Mark
Mark

Reputation: 6455

You're using class variables that can interfer with each other. Your Test class will only ever have one class variable called @@start_time associated with it.

This means if another user sees the form, they will reset the @@start_time for every user currently on it.

To prevent this, use instance varaibles. When a new user sees the form, they will make a new instance variable that is tied to their instance of the class, rather than the class itself. This will allow users to have different start and end times.0

All you need to do is change every @@ to @. So instead of @@start_time', try@start_time` throughout your code, and the same for end_time.

Upvotes: 0

Vishal
Vishal

Reputation: 828

Your solution will create conflicts when more than two users try to edit simultaneously, So basically what idea I have is:

  1. Add one virtual attribute in your model edit_start_time You don't need attribute for endtime because it can be directly fetched by Time.now at any time.

  2. Set edit_start_time value in edit method like:

      @model.edit_start_time = Time.now.utc #you can use any  
    
  3. In update method directly calculate edit time like:

    total_update_time = Time.now.utc - @model.edit_start_time.utc
    

If you are unaware of how to create virtual attributes then there are so many questions on StackOverflow as well as docs. I am not explaining how to do it here because its the different topic.

All the best

Upvotes: 1

Related Questions