开发者

Read only mode for Ruby on Rails application

I have an interactive Ruby on Rails application which I would like to put into a "read only mode" during certain times. This will allow开发者_如何学Go users to read the data they need but block them from actions that write to the database.

One way to do this would be to have a true/false variable located in the database that was checked before any write was made.

My question. Is there a more elegant solution for this problem out there?


If you really want to prevent any database write, the easiest way I can imagine would be to override the readonly? method of a model to always return true, either in selected models or maybe even for all ActiveRecord models. If a model is set to readonly (normally done by calling #readonly! on it), any try to save the record will raise an ActiveRecord::ReadOnlyRecord error.

module ActiveRecord
  class Base
    def readonly?
      true
    end
  end
end

(actually untested code, but you get the idea…)


Another good one which I liked a little better is Declarative Authorization which is covered by Railscasts as well: Railscasts - Declarative Authorization


Permissions plugin? Something simple like cancan where you define what a user can do, when. It will allow you to display links, or not, and restrict access to controller actions. The railscast will explain better than I can.

http://github.com/ryanb/cancan

http://railscasts.com/episodes/192-authorization-with-cancan


Zargony's solution seems to be the best one, but I would like to add to it a bit.

So, about his code:

This works nicely. A good solution is to add this in an initializer and run this code only if an env var is set, so that you can choose whether to run the app in read-only mode on launching the app.

if ENV['READ_ONLY'] == 'true'
  module ActiveRecord
    class Base
      def readonly?
        true
      end
    end
  end
end

And then run the server from command prompt like READ_ONLY=true bin/rails s. Also, adding

rescue_from ActiveRecord::ReadOnlyRecord, with: ->() {
  flash[:alert] = "The site is running in read-only mode. We are going to return to full operation soon. Thank you for your patience!"
  redirect_to root_path
}

to the ApplicationController (that all of your controllers should inherit from) is a nice way to show the users what is going on.


The answer by Zargony will work well but raise an exception if your application is trying to write anything. If you want your application to fail silently on writes so that it doesn't show error pages on each operation (e.g. if you update a timestamp on login in your code, you will get an exception), you can use the approach below:

   unless Rails.env.test?
      class ActiveRecord::Base
        before_save do
          raise ActiveRecord::Rollback, "Read-only"
        end

        before_destroy do
          raise ActiveRecord::Rollback, "Read-only"
        end
      end
    end
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜