Rails initialize default value in session - ruby-on-rails

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.

Related

Ruby on Rails - Use date to trigger action

I have an object that has an end date which is created using the callback after_create.
I'm wondering where the best place is to include the logic which would trigger an action when the object expires. (Time.now.in_time_zone > Object.end_date)
I'd like to create a method that checks whether an object has the attribute repeat as true or false. If it's true and the current date is passed the end date of the object, it should add 7 days to the end date of the object.
I have a method which checks whether the object is still valid but it's a boolean and I use it multiple times in the view so if I include it there, it gets executed multiple times before the view is even updated and I end up adding too many days to the end date.
Is it possible to have an action in your view file which is called automatically when the page loads if it falls under a certain condition? I'm guessing this is bad practice because I've read a few articles about avoiding too much logic in your view files.
I'm sure there are many ways of doing this so could you please let me know what methods you've used to overcome this?
Let me know if you need any more information.
You could consider using a Controller before_action, which would be called as you mentioned before the page loads.
Adapting the example in the Rails docs at http://guides.rubyonrails.org/action_controller_overview.html#filters
class MyObjectsController < ActionController::Base
before_action :object_expire, only: [:show]
private
def object_expire
# perform some logic here
if #my_object.expired?
#expired_result = #my_object.do_repeat
end
end
end
EDIT - limit before_action to show actions only

Disable logged_in filter for precise URLs

I am quite new to Rails, so please let me know if I don't use the correct terms.
I am trying to create a website that lets people create their own elections. The latest version of the website is available here.
People creating the elections have to register. The elections are only viewable and editable by logged in members (You don't want anyone to be able to see your election).
For this reason, I have this at the beginning of my election controller :
class ElectionsController < ApplicationController
before_filter :logged_in?
Logged in users access the elections via this kind of url : http://spo2tu.be:8001/elections/:id
The person creating the election defines a list of voters that will have to vote for a candidate.
What happens is that for each voter, a unique url is generated and sent by mail. The URL are of form : http://spo2tu.be:8001/elections/:id/votes/:long_generated_id
Example : http://spo2tu.be:8001/elections/1/votes/Y2_8TDL8Hkpz2MzzV_bpgw
My issue is that due to the heritage of the before_filter, non logged_in users see an error when reaching this URL .
The error is the following :
undefined method `elections' for nil:NilClass
#election = current_user.elections.find(params[:election_id])
What I think happens is that since the election has a logged_in before filter, it is impossible to get a reference to it in a deeper URL.
Since those URLs are unique, temporary and generated, I would like to let the persons having access to them also access the elections; hence bypassing the before_filter.
What would be the proper way to achieve this?
One possible solution I see would be to avoid nesting and change the URL to be of kind http://spo2tu.be:8001/votes/Y2_8TDL8Hkpz2MzzV_bpgw directly, but that wouldn't solve the issue since voters still need to have access to the election to see the description.
Thanks for the help!
You should specify for with method you want to check if the user is logged in.
so change before_filter :logged_in? to before_filter :logged_in?, only: [:edit, :new, :destroy]
And you are probably using this method of logging in.
And this depends on a session being present for current_user method to work.
So I suggest you don't use this to look it up but you use a params in url to specify which user is trying to access the election.
Hope it helps. :)
So, after the suggestion from Ramon Gebben, the problem comes indeed from this line :
#election = current_user.elections.find(params[:election_id])
Since users are not logged_in, current_user is not defined, which lead to the error.
Changing this line to
#election = Election.find(params[:election_id])
solve the issue.

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

Ruby saving "Model.all" into application-wide variable

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.

How to intercept information from a Rails logger?

I'm currently using Rails v2.3.5 at work and I'm quite new both to the language and the framework. What I need to do is to capture certain information every time a user requests a webpage (user's IP address, URL accessed, Date and time of access and the time the page took to render) and store it in a database.
I've noticed that all this information is contained in the default Rails' logfiles, but I'm trying to avoid having to parse the logfile to collect this information. What I would like is some way to hook to the logger and intercept this information or perhaps extend the logger and use my extended version instead of the default Rails one (ActiveSupport::BufferedLogger).
Maybe ever other solutions that don't require logs?
Thanks in advance.
What you probably need is a before_filter block in your ApplicationController to perform whatever action you need to do. From there you can create whatever database records you need. For example:
class ApplicationController < ActionController::Base
before_filter :log_user_info
protected
def log_user_info
# Activate a custom logging method on a model
UserActivity.log!(
# ... User parameters
)
end
end
Hooking in to the logger is probably a bad idea as that's an indirect way to get that information. You may need to extract data from this for historical reasons, though.

Resources