Ruby saving "Model.all" into application-wide variable - ruby-on-rails

I have a model called Business, and I want to save Business.all into a variable I can access from another part of my Rails application. What is the best way to do this? I am fairly new to Ruby/Ruby on Rails and I know of class and instance variables but I am a bit cloudy on this.
Thanks!

If you want this to be accessible throughout the entire application, you could put it into the application controller found in app/controllers/application_controller.rb.
Example:
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :find_all_businesses
def find_all_businesses
#businesses = Business.all
end
end
Hope this helps.

You probably want to look at Rails caching. There is a good screencast here:
http://railscasts.com/episodes/115-caching-in-rails-2-1
It also applies to rails 3. This will allow you to expire the cache if a business is added for example.

Related

Ruby on Rails DRY Best Practice

I'm learned RoR programming through Mickael Hartl's tutorial, which I really enjoyed.
Now I'm developing an application with 8 types of objects.
For each object, I need to assign a status, coming from a statuses table, and to assign current user's name.
In each controller, in private section, I wrote a statuses_list function and a current_user_name, which make these data available to select fields in the forms respectively.
This does not sound DRY-like that much.
Would it be relevant and secure to write such functions as helpers so the data are available anywhere in my application ?
Thanks for your advice,
Best regards,
Frédéric
Move those methods to their home classes. Status.list() and User.current_user(). That's generally how people solve the problem "everyone needs a current_user, but nobody wants a $current_user global variable.
Then assign the current_user very early in your before_filters, when the authentication system identifies the user. And read /Confident Ruby/, by Avdi Grimm, for a very good write-up on how and why to create a Guest user, for current_user to return if nobody is logged in: http://devblog.avdi.org/2013/08/26/confident-ruby-is-finished/
Putting the methods in a helper file is the best way to make them available in your views, but if you also want to make these methods available in your controllers, then put these as methods in ApplicationController and at the top specify:
helper_method: :statuses_list, :current_user_name
Hope that helps.
To make your code accessible throughout your application, you have to mention it in helpers. This is ofcourse a DRY principle and would help you to reduce the same line of code again and again..
I would recomment using inheritance to give some controller some same methods.
Create a SuperClass that extends ApplicationController like:
class SuperController < ApplicationController
[...]
end
and subclass it
class MyControllerClass < SuperController
[...]
end
Put the repetitive stuff in the SuperController - et voila ! MyControllerClass inherits methods SuperController so you dont need to repeat them.
Well, thanks to all the answers collected, here is how I did :
Defined a set_statuses_list method in a ParametersHelper
Added include ParamtersHelper to the ApplicationController
Added before_action :set_statuses_list in each of my 8 objects controllers
It feels like a good balance, and I'll be happy to get comments about it.
Note that the current_user method was indeed already available through the SessionsHelper.
Thanks for your help,
Best regards,
Frédéric

Package instance variables in rails controllers?

I'm overwhelmed by managing instance variables in controllers so am thinking if there's a better way to manage them.
My situation is, I'm having a PagesController that handles the front page rendering. In the front page, I have multiple small forms that originally belong to different controllers (For example, make a new post form, and there's a PostsController dedicated for it but for convenience you can make an easy post just at the front page.) and they all need their corresponding instance variable to hold the form (e.g. new post form needs a #post object).
It turns out to me, that I have to manually add these instance variables into my PagesController#index in order to make the forms work, so many lines become just
#post = Post.new # similar for other objects
#some_other_var = OtherController.new # another one
#one_more = AnotherController.new # again
# even more #variables here when the website is big
If this doesn't seem bad enough, think about when create or edit action fails (e.g. does not pass validation) and we need to render the previous page. We need to add these lines AGAIN. Actually we need to include ALL THESE VARIABLES whenever there's a render.
It seems very cumbersome to manually type such code to every action that needs them and it's so easy to just miss one or two of them when the website gets complicated.
So I'm wondering if there's a better way to manage such variables so that we only need to include them once instead of writing the same code every time.
You can create a before_filter something like:
class ApplicationController < ActionController::Base
...
...
protected
def instance_variables_for_form
#post = Post.new # similar for other objects
#some_other_var = OtherController.new # another one
#one_more = AnotherController.new # again
# even more #variables here when the website is big
end
end
and use it like:
class PagesController < ApplicationController
before_filter :instance_variables_for_form, only: [:action]
...
...
end
and then you can call it explicitly too from any action whenever needed.
If those variables can be logically grouped, you should consider putting them into Presenter objects.
Here is a good blog post explaining the idea: http://blog.jayfields.com/2007/03/rails-presenter-pattern.html

Rails global variable

Im using bootstrap & rails and have a user model and post model..users create posts (collections)..
with bootstrap in the navbar i want the user to be able to click a dropdown which displays the name's of their posts..i did this on one controller with a private method and a before_action but i don't want to do this for all the controllers and it didn't work for the application controller...
is there a better way to do this??
I was doing this
def list
#user = User.find_by_username(params[:id])
#collections = #user.collections
end
and a
before_action :list
at the top of the controller
What's the most semantic way to accomplish this??
If you could move both to your application controller, then it would be available to any controller. More generally, I'm not sure if this is the best approach to solve your problem.
These tips might also be useful.
Are you using devise? Or some other authentication plugin? If so you're likely going to have a current_user helper. This would allow you to simply do #collections = current_user.collections
To the extent possible, I recommend using more descriptive names for your actions and parameters. def fetch_list_collections might be a better name or instead of passing a param named id, perhaps your param should be named username. These naming conventions become extremely important both for others who might look at your code as well as for yourself if you return to it and are trying to remember what you wrote N months ago.
Your list action is generating a N+1 queries. Meaning that you're hitting the database multiple times when you should do so just once. See the rails guide on this. You might also look at ways to avoid this w/ devise. Devise is pretty well documented and I'll bet there is something in the wiki discussing this.
You may want to consider limiting when you call this action - at a minimum - a post request to an update action? What about before they've logged in? current_user might be nil and you'd have an error attempting to call a collections method on nil.
Take your time learning this stuff. You don't have to learn it all at once, but I thought the above might be helpful.
I got it to work with this in the application controller
before_action :list
private
def list
#collections = current_user.collections
end
thanks #arieljuod

In Rails filter all ActiveRecord calls

I have a rail app which is meant for users from different Organizations.
I want to make a mechanism that will make sure that when a user gets any data from the db, it can be only from his organization.
I want that to be true even if there is a bug in my queries i.e. I want this filter to be independent of all other code.
How can I implement this filter to run on all ActiveRecord calls?
can I use "default_scope" (http://apidock.com/rails/ActiveRecord/Scoping/Default/ClassMethods/default_scope) for that but apply it to all models some how?
Thank you!
For me the only way to achieve that properly is by scoping all your methods to something like
user_organization.<relation>.<query>
You can for example have a user_organization method in your ApplicationController
class ApplicationController < ActionController::Base
def user_organization
current_user.organization
end
end
The default scope does not accept parameters if I'm not wrong, and I highly discourage you using for anything.

Rails initialize default value in session

I have a web application, and i want to store user prefered stylesheet in session, and i need to fill it by default to some default till user not log-in or etc. For this purpouses i use session (probably not best solution but it does not matter), and i need a place where i can initialize this variable. Example :
session[:user_theme] = 'default.css'
i dont want to check it every time before filter in some function, i want to initialize it once and then only change via UI.
Can you help me to find better place to do that?
I think application controller is a good place. Something similar should work.
class ApplicationController < ActionController::Base
before_filter :set_theme
def set_theme
session[:user_theme] ||= (current_user ? current_user.preferred_theme : 'default.css')
end
end
EDIT
oops i did misread question. But i do agree with Niels, it is the best place to put. And ||= aperator will initialize it only once.

Resources