Permanent variable in Rails

ぃ、小莉子 提交于 2020-01-14 13:28:06

问题


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.


回答1:


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




回答2:


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).




回答3:


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.




回答4:


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




回答5:


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



回答6:


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



回答7:


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 }


来源:https://stackoverflow.com/questions/9490985/permanent-variable-in-rails

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!