Model Access throughout Entire Rails Application - ruby-on-rails

Ruby 1.9.3 + Rails 3.2.8
I have a view that is rendered on every page in my app inside a partial:
<span id="sync-time">
<%= #sync.dropbox_last_sync.strftime('%b %e, %Y at %H:%M') %>
</span>
In order to use my syncs model and have access to the dropbox_last_sync method, I have to include it in every controller throughout my app. For example:
class EntriesController < ApplicationController
def index
#sync = current_user.sync
end
end
...
class CurrenciesController < ApplicationController
def index
#sync = current_user.sync
end
end
...etc.
Is there a way I can make the syncs model available everywhere by including it in my Application Controller somehow?

You should be able to add a before_filter in your application controller:
before_filter :setup_sync
def setup_sync
if current_user
#sync = current_user.sync
end
end
You need to be careful that your setup_sync filter runs after whatever code you are using to set up your current_user. This is probably another before_filter though so provided you have before_filter :setup_sync declared after your current user filter it will work fine.

This is better:
class ApplicationController < ActionController::Base
before_filter :authenciate_user!
before_filter :index
def index
#sync = current_user.sync
end
end
You're using current_user always, so you need to have before_filter :authenciate_user! here aswell and above the other one.

Related

Rails/Devise: Restore session without going through full auth process?

I'm using Devise + ominauth2 to allow users to sign in via different services. If they sign in they get a slightly better experience but if not life still goes on. However I don't see a way with Devise to have a page that allows both authenticated and unauthenticated access.
For example:
class SomeController < ApplicationController
before_action :authenticate_user!
def some_action
end
end
In the above controller, some_action is only accessible if the user authenticates. But what I actually want is something more like:
class SomeController < ApplicationController
def some_action
loadSessionFromCookieIfExists
end
end
Then, I can use user_signed_in? in my views. But this doesn't work because authenticate_user! will redirect them elsewhere. Unless there is an authenticate_if_possible method?
So what I have now, which is really gross is:
class SomeController < ApplicationController
before_action :authenticate_user!
skip_before_action :authenticate_user!, :only=>[:no_auth]
def action
do_stuff
return
end
def no_auth
do_stuff
return
end
private
def do_stuff
render :template => "action"
end
end
I should add, that omniauth2 doesn't support rememberable out of the gate so it's possible this is all supposed to work just fine and the problem is with omniauth2.

Rails. Set default timezone when current_user loaded

I'd like to change the application time zone when current_user (Devise) is initialized, like this:
Time.zone = current_user.settings(:main).time_zone
What is the best place in the app to put this code at (application controller, before_filter is not a solution)?
I think the safest approach here would be to use the around_action like such, make sure to specify which action you want this to happen on:
class SomeController < ApplicationController
around_action :set_time_zone, only: :show
private
def set_time_zone
if current_user
Time.zone = current_user.settings(:main).time_zone
end
yield
end
end

Rails: Sidebar Conflict

I've a sidebard to display #notices
<% #notices.each do |notice| %>
<li class="list-group-item notice"><%= short_auto_link(notice.content) %></li>
<% end %>
I also have a admin interface to manage notices(e.g. CRUD).
The problem is that when I open edit or new page for notice.
It will report undefined method 'each' for nil:NilClass for <% #notices.each do |notice| %>.
Now I can only get away with this by adding a <% if #notices %> before the .each block.
UPDATE:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_filter :set_notice
def set_notice
#notices = Notice.all
end
end
app/views/notices/_notice_board.html.erb:8:in `_app_views_notices__notice_board_html_erb__624099781_29657256'
app/views/layouts/application.html.erb:19:in `_app_views_layouts_application_html_erb___900927418_28913616'
You need to change this:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_filter :set_notice
def set_notice
#notices = Notice.all
end
end
to this:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_filter :set_notices
def set_notices
#notices = Notice.all
end
end
Things you can learn from this is that always try to avoid such naming conventions of a method. Since, you're setting #notices(plural), your method name should also be plural: set_notices. In your case set_notice method is being overridden by method defined with the same name in NoticesController. Changing the method name as mentioned above should fix the issue.
If your sidebar is shared only across all actions of your admins_controller define a private method to get #notices in admins_controller, and put before_filter at the beginning of the controller.
in admins_controller ::
before_filter :prepare_notices
def show
end
def edit
end
...
private
def prepare_notices
#notices = YOUR_QUERY
end
If your sidebar will be rendered across the whole website move the code to your application_controller and before any request to you server this method will be executed.
If your sidebar will be rendered with some actions in your website you should put the get_notices method in the application_controller and use before_filter in each controller specifying the actions that will render the sidebar only.

ruby on rails best place to put layout database code (common database calls)

I'm making a control panel (user accounts) in rails.
in the layout I need to show things like messages or notifications (facebook-like style).
the problem is these things require an access to database and I'm not sure where to put this code because it's not related to a controller, but the layout is shared with multiple controlers.
so where is the best place to put the code to fetch messages from database should I put in the layout itself (I don't think its right), or as helper ?
the best solution was to build a control-panel controller which handles authentication and permissions and loads common user data from database such as messages...
here is an example code
class ControlPanelController < ApplicationController
before_filter :authenticate_user!
before_filter :get_user_data
helper_method :mailbox
authorize_resource
protected
def get_user_data
#header_conversations=mailbox.inbox.limit(3)
#uevents= Event.scoped
#uevents= #uevents.after(Time.now)
end
def mailbox
#mailbox ||= current_user.mailbox
end
end
and then all the classes in my web application extends this class :)
I found a way is to use before_filter. by defining the filter in the ApplicationController (so that you can access it from any controller).
class ApplicationController < ActionController::Base
# ..
protected
def load_messages
#messages = Message.all
end
end
and then in the any controller:
class FooController < ApplicationController
before_filter :load_messages
def index
# #messages is set
end
end

Ruby on rails: How can I get values from a database in application.html.erb?

How can I get values from database in application.html.erb? I need to get those values for whole project. Those values will stay forever to all pages. How can I pass values to application.html.erb?
Is there anything like beforeRender?
Is there anything like appcontroller.rb to override actions?
You could use an application wide before_filter - like so
class ApplicationController < ActionController::Base
before_filter :load_application_wide_varibales
private
def load_application_wide_varibales
#var = Model.where :condition => "whatever"
end
end
#var would then be available in all your views
cheers
you can put method in the application controller
before_filter :load_data
def load_data
#data = Data.all
end
All controllers inherits ApplicationController, so data will be loaded at all actions. Now you can use #data at you application.html.erb file
The best way is probably to create a method in your application controller and declare it a helper method. Then you can call that method in application.html.erb. For example if you want to be able to use the current user throughout your application you'd do something like this:
class ApplicationController
helper_method :current_user
def current_user
#current_user ||= User.find(session[:user_id])
end
end
Then in application.html.erb you can do the following:
Hello <%= current_user.name %>
It's also possible to use before_filter like to other answers suggest, but in this solution the database only gets hit when it's necessary. With before_filter it always gets hit.

Resources