Rails - Setting time_zone dynamically as per user selection - ruby-on-rails

I appreciate your help one of the features working on for my new website!
This is regarding the dynamic time_zones as per the requirement user would be able to choose from set of pre-defined time_zones say us_zones. When the user picks the zone the entire site should be set/updated to TimeZone.
However, at present the new time zone is not becoming updated into Apache and the updation of time zone happens only at the restart of the server.
I was thinking in the lines of using Rails Initializer class and initialize_time_zone() methods, but even this requires the rails server to be restarted.
Thanks in advance!

Place to Application controller something like this:
def set_api_time_zone
utc_offset = current_user_session && current_user_session.user ? current_user_session.user.time_zone_offset.to_i.minutes : 0
user_timezone = ActiveSupport::TimeZone[utc_offset]
Time.zone = user_timezone if user_timezone
end

Related

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.
Your solution will create conflicts when more than two users try to edit simultaneously, So basically what idea I have is:
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.
Set edit_start_time value in edit method like:
#model.edit_start_time = Time.now.utc #you can use any
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
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.

Rails - Getting datetime_select into user timezone for model validation

I tried to get this answered with no luck so I'll try again.
I've implemented the railcast timezone goodies to allow the user to set their time zone. It works. Time.zone.now gives the correct time zone. It's in here
http://stevenyue.com/2013/03/23/date-time-datetime-in-ruby-and-rails/
I have events and have been trying to get the datetime_select in my form to give me a time that is also in the user's time zone.
My goal is to be able to compare it to current time (Time.zone.now) to validate that the start time is not before current time. And eventually end time > start time etc.
I've tired several ways including this one with no luck...
This one - he answered his own question later (is exactly my problem)
Rails datetime_select posting my current time in UTC
def start_date_cannot_be_in_the_past
if date_start.in_time_zone(Time.zone) < Time.zone.now
errors.add(:date_start, "has already passed")
end
end
The above doesn't seem to work because you can't extract date_start just like that. It's separated into different components, so I tried to do something like this
def start_date_cannot_be_in_the_past
date = DateTime.new(params[event][date_start(1i)].to_i, params[event][date_start(2i)].to_i, params[event][date_start(3i)].to_i, params[event][date_start(4i)].to_i, params[event][date_start(5i)].to_i)
if date.in_time_zone < Time.zone.now
errors.add(:date_start, "has already passed")
end
end
In my model I can't access params so I don't know how to get this to work...
I want to move to a jquery calendar/time picker if possible as I can't seem to get this work.. but any suggestions on alternatives or on this is appreciated..
Make sure you have this line in your model:
validate :start_date_cannot_be_in_the_past
and then this method can be something like:
private
def start_date_cannot_be_in_the_past
errors.add(:date_start, "has already passed") if self.date_start < Time.zone.now
end
See this for more information.

Rails initialize variables in server startup

I want to initialize a variable in rails and use it in a controller's action, but the variable should have a fixed value when the server starts. I have tried defining it inside a controller's action and it get's the same initialized value for every request. For example, i want to initialize a date.now and have the same date after 15 days also.
Update
I am implementing a coming soon page in which a timer is shown 15 days from now. If i implement it in a action inside a controller, it shows new date every time the action is invoked.
Please Help
If you want to create a CONSTANT in rails then you can simply put it into the initializer file. For eg, create a file name constants.rb inside initializer:
#config/initializers/constants.rb
TEST_VALUE = 10
And to access this CONSTANT from your controller, just call for TEST_VALUE. for eg,
#controllers_path/some_controller.rb
.....
def some_def
#value = TEST_VALUE # this will be enough to fetch the constants.
end
But, make sure you restart your server after changing the intializer.
You're looking to create a constant, which is basically a variable which doesn't change its value
You'd typically set these with initializers:
#config/initializers/your_initializer.rb
YOUR_CONSTANT = your_date
To maintain a persistent date, you'll have to give some more context on what you're using it for. It will be difficult to create this each time Rails loads (how to know which Time.now to use), so giving us more info will be a good help
You can also use an opposite approach. Assuming you should know the date when the new feature comes (for example 2014-04-04 18:00) you can just find a number of seconds left till the target date:
#seconds_left = Time.parse('2014-04-04 18:00').to_i - Time.now.to_i
then pass it to client side and implement a timer. So you'll just need to store a string representation of a target date.
Obvious disadvantage of this approach is that you should adjust that target time each time you want to introduce a new feature.

Trouble with the speed of using in_time_zone

I am using Ruby 1.8.7 and Rails 3.0.3. Even though currently all of my users are in the same time zone as my server, I thought that in preparation for world domination I'd get rid of all of my RubyTimeObjIGotOutOfMyDb.getlocal calls and replace them with RubyTimeObjIGotOutOfMyDb.in_time_zone(user_timezone) where the user's timezone is a column in my user's table. What happened is now my page takes maybe 5 or 6 times as long to load. Is this the wrong strategy? Is there a better way I should be preparing for users in different timezones from my server?
watching this railscast
I think you just need to do
controllers/application.rb
before_filter :set_user_time_zone
private
def set_user_time_zone
Time.zone = current_user.time_zone if logged_in?
end
And all the times will be converted when fetching from db
If times are not in the current timezone, try this in the views (or in console for testing)
Time.now.in_time_zone
UPDATE:
If you are doing that call in_time_zone(zone) many times, I think it's fetching the corresponding time difference many times, the way the screencast tells to do, it will fetch only one time and use it in every conversion.

Rails: Showing the latest deploy date in web app

I'd like to show in our app when the latest production deploy was made, as a means of showing an ongoing commitment to improvement, etc, etc.
Off the top of my head I'm thinking of getting a last_updated_at from one of the files, but I'd like to hear other thoughts.
What's the best way to get the date of the latest production deploy dynamically?
Thanks,
Josh
Thanks to mpd who pointed me on the right direction.
For those interested in doing something similar, this is a quick and dirty method that probably can be refined and refactored.
In app/controllers/application_controller.rb put this method in the private section:
private
def app_last_updated_at
if File.exist?(RAILS_ROOT + "/REVISION")
timezone = "Mountain Time (US & Canada)"
#app_last_updated_at = File.atime(RAILS_ROOT + "/REVISION").in_time_zone( timezone )
else
#app_last_updated_at = "Not Long Ago."
end
end
Obviously, replace the timezone with your own (or you can do something fancy for individual user timezones).
In order to have this run all the time I use a :before_filter and put it at the top of your application_controller.rb.
before_filter :app_last_updated_at
And then to actually show this last updated at date, you just throw this or something like it in a layout or a partial or whatever:
<%=
unless #app_last_updated_at.nil?
if #app_last_updated_at.is_a? Time
#app_last_updated_at.to_s(:long)
else
#app_last_updated_at
end
end
%>
Hopefully, this helps others. I'm not keen on having it run in the ApplicationController for every access, so suggestions would be appreciated.
You can do it pretty easily with Capistrano. Take a look at this link I think it does exactly what you want Deployment date

Resources