I want to store a single variable across all my users in a rails application.
This variable is just an integer that can change sometimes.
I want it to persist across different launch of the server.
I want any controller to be able to change (and persist) the value
It sounds really easy to do, but I can't find any tool that would do it for me...
I would create a Key/Value table and model.
So far, it would only store one key, the integer you're talking about. Later, it could do a little more. The value could be a JSON document so you can store any kind of JSON supported native types very easily.
Simply create a model with one attribute. And then create one instance of that model. Then access this from your controllers
for example
Model.first.attribute
I ended up using the gem rails-settings-cached
It provide an easy way to access a persistant variable:
Setting.a_setting = 42
Setting.a_setting #42
Related
I'm making use of Google API client gem which returns data and is then wrapped in the an object. I want to use this data between sessions. How should I store it? I thought at first I could serialize it then put it into a table, but ran into problems with the type of object it is an gave up. Actually thereafter I thought it would be neater to take the data I need and put it into an array of hashes (eg. for youtube videos - title, id, thumbnail etc) so I extracted what I needed and done so. Now, I have an array - should I store it in the database for the user or should I put it into a session var? Session var seems easier, no need to create an additional table etc but does that mean it will be stored as a cookie? Might be a rather large cookie then. Anyway advise here would be much appreciated.
First, with database storage: with ActiveRecord you can simply store JSON. So, if your object can be serialized correctly, than there are no problems to store it in DB. just add this line to your model:
serialize :data, JSON.
Though, I think you can perfectly use session var for that purpose. By default, yes, it will be stored as a cookie - but if you think it's too much information, you can configure rails to use server-side storage instead.
I'm starting to use Redis, and first thing my code is not too DRY, and was going to consolidate it in the application.rb and controller. Is this the best way to go, or should I make a new Class called Redis, and have all the logic in there?
My models are currently Customers, Orders, Products, and I'm using a lot of counters.
You will probably need a combination of new and existing model classes.
In many cases you can just drop the model used by the view directly into the datastore, which saves repetition. However, there will always be some places where the needs of the view and the datastore are different.
For example a property that appears as a list of values in the view may need to be stored as a separate set key rather than serialized with the other properties of the model.
This is mostly of a design pattern question. I have one type of model that I'm going to get the data to create them from multiple sources. So for example one record my be created from an API where another is created via screen scraping with Nokogiri.
My issue lies in how best to abstract out these different data sources. Right now I'm building lib classes that return the same hash which I then use to set the attributes of the model. But I'm wondering if this isn't more of a case to use STI. Or if there is some other way of doing this I'm just not thinking about.
I think your design decision would depend largely on what attributes need to be stored. From your description, it sounds like you have a model with multiple data sources, but which would be storing the same attributes regardless of the source. In that case STI seems like overkill. When you retrieve a row from the table, does it matter whether the source is the API or the screen scraper? If not, then you could just define separate methods for each data source and use the appropriate method in the controller.
#instance = MyModel.new(:datasource=>"API")`
I'd say don't worry about inheritance (or mixing in code from modules) unless you really need to. There are some gotchas -- STI is not fully supported by some gems/plugins, for example.
I don't know if this is bad form or not, but I needed to set a file path that's accessible to all objects within actions in my controller. One action in the controller creates a file and stores it in a path. Another action serves the file using send_file. The only place I have been storing variables is along with an object in the model. However it seems really silly to store a URL in arbitrarily the first object, or copy the url over all objects. What's the best way to do this?
I hope this was clear.
If this is a file path that is specific to the user of the site, so each user has a different path, you can store it in the session.
session[:file_path] = generate_file!
…user goes to the next page…
send_file session[:file_path]
You could create a method in your application controller that returns the path. This method will then be available throughout your controllers. Don't know if this is necessarily "best practice" but it works for me.
The answer depends on your context. Here is some generic advice:
If there's one file per model, then you need to store one path on each model that has it.
If there's one file shared by several models, but your objects are relatd on a hierarchy, you need to store it on the "father object" - the one that has_many others. The other objects will have to do self.parent.file_path.
Finally, if there's one file used by several non-related models, then I don't know what to suggest, except that maybe there's a better way to organize your models.
What objects are you trying to store, and what relationships are between them?
Imagine a web application written in Ruby on Rails. Part of the state of that application is represented in a piece of data which doesn't fit the description of a model. This state descriptor needs to be persisted in the same database as the models.
Where it differs from a model is that there needs to be only one instance of its class and it doesn't have relationships with other classes.
Has anyone come across anything like this?
From your description I think the rails-settings plugin should do what you need.
From the Readme:
"Settings is a plugin that makes managing a table of global key, value pairs easy. Think of it like a global Hash stored in you database, that uses simple ActiveRecord like methods for manipulation. Keep track of any global setting that you dont want to hard code into your rails app. You can store any kind of object. Strings, numbers, arrays, or any object."
http://github.com/Squeegy/rails-settings/tree/master
If it's data, and it's in the database, it's part of the model.
This isn't really a RoR problem; it's a general OO design problem.
If it were me, I'd probably find a way to conceptualize the data as a model and then just make it a singleton with a factory method and a private constructor.
Alternatively, you could think of this as a form of logging. In that case, you'd just have a Logger class (also a singleton) that reads/writes the database directly and is invoked at the beginning and end of each request.
In Rails, if data is in the database it's in a model. In this case the model may be called "Configuration", but it is still mapped to an ActiveRecord class in your Rails system.
If this data is truly static, you may not need the database at all.
You could use (as an example) a variable in your application controller:
class ApplicationController < ActionController::Base
helper :all
#data = "YOUR DATA HERE"
end
There are a number of approaches that can be used to instantiate data for use in a Rails application.
I'm not sure I understand why you say it can't fit in a Rails model.
If it's just a complex data structure, just save a bunch of Ruby code in a text field in the database :-)
If for example you have a complex nested hash you want to save, assign the following to your 'data' text field:
ComplexThing.data = complex_hash.inspect
When you want to read it back, simply
complex_hash = eval ComplexThing.data
Let me point out 2 more things about this solution:
If your data structure is not standard Ruby classes, a simple inspect may not do it. If you see #<MyClass:0x4066e3c> anywhere, something's not being serialized properly.
This is a naive implementation. You may want to check out real marshalling solutions if you risk having unicode data or if you really are saving a lot of custom-made classes.