Rails: Showing the latest deploy date in web app - ruby-on-rails

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

Related

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.

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 - Setting time_zone dynamically as per user selection

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

Permanent variable in Rails

Lets say that on top of my Rails app there is a bar with piece of text displayed - latest hot deal, scheduled downtime notfication, something like that. It's a single, on of a kind information that needs to be accessed on basically every request, and may be updated from time to time. What is the best way to achieve this?
What I'd like to do is some kind of permanent global variable (accessible from controllers).
It will be updated very rarely, so there's no problem if for some time after update there will be an inconsistency between workers.
On the other hand, it should be persistent in case of server fault (periodic backup is enough).
It will be accessed really often, so it should be as fast as possible - preferably stay in memory.
Also, it's only one of a kind, so I'd really prefer not to bloat the app with a dedicated database model.
Something like that is damn easy in Node.js for example, but I couldn't find a single way to achieve this in Rails. What shall I do?
EDIT
Thanks for the answers so far, but while they're inspiring, I think that I should stress out one key functionality that they're all missing. The variable should be editable inside the app and persistent. While it's possible to edit your variables, in case of server restart I'm back to the default - which is bad.
It really depends on what you are looking for. You could do something very simply by putting it in your application_controller.rb
class ApplicationController < ActionController::Base
def system_message
"Come buy our amazing .99 iphone chocolate bar apps, with 100% more gamification!"
end
end
That function (and string) is then accessible from any controller in your application. You could also specify something in the after_initialize block in your application.rb file.
config.after_initialize do
::MYTEXT = "MY SUPER AMAZING TEXT"
end
You could also create your own file under the initializers directory, which is preloaded in rails.
so siteAnnounce.rb
MYANNOUNCEMENT = "NOW LISTEN TO ME!"
You may also want to check out this Railscast video about site wide announcements
I would store it in the database and let caching take care of it.
I feel that global variables are fine, when appropriate, for code that needs to share that common value in many places but that is the code, not the the user view.
This is clearly true in this case as the OP has bolded 'editable by the app'. So I would have a view that lets the users enter it, it gets stored in a db table and then recalled as needed (as cached once used once).
Well I had faced a similar problem.
My problem was I needed a global variable in all the levels (MVC).
We went to use Memcache to store the variable.
May be you can go for a similar solution.
And as an added bonus you can change it throughout the program.
You could declare it as a constant in an initializer:
config/initialzers/foo.rb:
MYVARIABLE = 'some string'
Accessible from anywhere in your application as MYVARIABLE
Ok, so here's what I did. Instead of just putting the value to an initializer, I've made there a simple class that handles it. The variable itself is stored in a predefined file. Besides of reading the file upon the initialization, the class updates file when the value is changed, and also re-read the file periodically to maintain consistency across workers. I've also put there some basic JSON handling and backup functionality to make life easier.
For anyone interested, here's the important code:
class Pomegranate
def initialize
#delay = 30.minutes
#path = "db/pomegranate.json"
#valid = Time.now - 1
validate
end
def get(*p)
validate
p.inject(#data) {|object,key| object[key] if object}
end
def set(*p, q, v)
hash = p.inject(#data) {|object,key| object[key]||={}}
hash[q] = v
end
def save
#valid = Time.now + #delay
File.open(#path,"w") {|f| f.write(#data.to_json)}
end
private
def validate
if #valid < Time.now
#data = ActiveSupport::JSON.decode(File.read(#path)) rescue {}
#valid = Time.now + #delay
#valid = Time.now - 1 if #data.empty?
end
end
end
$pom = Pomegranate.new
Source:
Where to put Global variables in Rails 3
Try putting it in your applicaton.rb like this:
module MyAppName
class Application < Rails::Application
YOUR_GLOBAL_VAR = "test"
end
end
Then you can call it with the namespace in your controllers, views or whatever..
MyAppName::Application::YOUR_GLOBAL_VAR
Another alternative would be using something like settingslogic. With settingslogic, you just create a yml config file and a model (Settings.rb) that points to the config file. Then you can access these settings anywhere in your rails app with:
Settings.my_setting
I've started putting constants and variables like this in the configuration object, e.g.
TestApp::Application.config.foo = 'bar'
TestApp::Application.config.something = { :a => 1, :b => 2 }

Profile a rails controller action

What is the best way to profile a controller action in Ruby on Rails. Currently I am using the brute-force method of throwing in puts Time.now calls between what I think will be a bottleneck. But that feels really, really dirty. There has got to be a better way.
I picked up this technique a while back and have found it quite handy.
When it's in place, you can add ?profile=true to any URL that hits a controller. Your action will run as usual, but instead of delivering the rendered page to the browser, it'll send a detailed, nicely formatted ruby-prof page that shows where your action spent its time.
First, add ruby-prof to your Gemfile, probably in the development group:
group :development do
gem "ruby-prof"
end
Then add an around filter to your ApplicationController:
around_action :performance_profile if Rails.env == 'development'
def performance_profile
if params[:profile] && result = RubyProf.profile { yield }
out = StringIO.new
RubyProf::GraphHtmlPrinter.new(result).print out, :min_percent => 0
self.response_body = out.string
else
yield
end
end
Reading the ruby-prof output is a bit of an art, but I'll leave that as an exercise.
Additional note by ScottJShea:
If you want to change the measurement type place this:
RubyProf.measure_mode = RubyProf::GC_TIME #example
Before the if in the profile method of the application controller. You can find a list of the available measurements at the ruby-prof page. As of this writing the memory and allocations data streams seem to be corrupted (see defect).
Use the Benchmark standard library and the various tests available in Rails (unit, functional, integration). Here's an example:
def test_do_something
elapsed_time = Benchmark.realtime do
100.downto(1) do |index|
# do something here
end
end
assert elapsed_time < SOME_LIMIT
end
So here we just do something 100 times, time it via the Benchmark library, and ensure that it took less than SOME_LIMIT amount of time.
You also may find these links useful: The Benchmark.realtime reference and the Test::Unit reference. Also, if you're into the 'book reading' thing, I picked up the idea for the example from Agile Web Development with Rails, which talks all about the different testing types and a little on performance testing.
There's a Railscast on profiling that's well worth watching
http://railscasts.com/episodes/98-request-profiling
You might want to give the FiveRuns TuneUp service a try, as it's really rather impressive. Disclaimer: I'm not associated with FiveRuns in any way, I've just tried this service out.
TuneUp is a free service whereby you download a plugin and when you run your application it injects a panel at the top of the screen that can be expanded to display detailed performance metrics.
It gives you some nice graphs, including one that shows what proportion of time is spent in the Model, View and Controller. You can even drill right down to see the individual SQL queries that ActiveRecord is executing if you need to and it can show you the underlying database schema with another click.
Finally, you can optionally upload your profiling data to the FiveRuns site for community performance analysis and advice.
This works in Rails 4.2.6:
o=OpenStruct.new(logger: Rails.logger)
o.extend ActiveSupport::Benchmarkable
o.benchmark 'name' do
# ... your code ...
end

Resources