I want a piece of content to display to first time visitors of a rails app, so I wrote a helper method that checks session and stores a cookie.
My controllers are set up like this:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
helper_method :first_time_visiting?
def first_time_visiting?
if session[:first_time].nil?
cookies.permanent[:first_time] = 1
end
end
end
class ItemsController < ApplicationController
before_action :first_time_visiting?
end
And then I'm calling the method in my view like this:
<% if first_time_visiting? %>
<div class="new-visitor-show">Test</div>
<% end %>
I should not be seeing "Test" after first visit, but I am. Am I using the helper method incorrectly?
You could use this (without helper):
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :first_time_visit, unless: -> { cookies[:first_visit] }
def first_time_visit
cookies.permanent[:first_visit] = 1
#first_visit = true
end
end
The function first_time_visit will be called only once, and so in the view :
<% if #first_visit %>
<div class="new-visitor-show">Test</div>
<% end %>
I think you should be checking the cookies instead session.
def first_time_visiting?
if cookies[:first_time].nil?
cookies.permanent[:first_time] = true
true
else
false
end
end
Related
In my Rails 7 application I've got two controllers:
class Context::FrontendController < ApplicationController
end
class Context::BackendController < ApplicationController
end
All my other controllers (and there are a lot of them) inherit from either the first one or the second one (but never both).
In my views I sometimes need to show or hide certain elements depending on if the current controller inherits from the FrontendController OR the BackendController.
How can this check be done?
In my views I sometimes need to show or hide certain elements depending on if the current controller inherits from the FrontendController OR the BackendController.
How can this check be done?
You can do this check (as shown by #mechnicov), but you shouldn't. Instead, use OOP.
class ApplicationController
def current_area
# raise NotImplementedError
:none
end
helper_method :current_area
end
class FrontendController < ApplicationController
def current_area
:frontend
end
end
class BackendController < ApplicationController
def current_area
:backend
end
end
Then
<% if current_area == :frontend %>
You can prettify this as you wish (make methods frontend? / backend?, etc.)
In your view you can use something like
<% if controller.class.ancestors.include?(Context::BackendController) %>
<%= show.some.content %>
<% end %>
May be create some helper
def inherited_from?(controller_class)
controller.class.ancestors.include?(controller_class)
end
And then
<% if inherited_from?(Context::BackendController) %>
<%= show.some.content %>
<% end %>
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.
I am having a action in application controller
def is_customer_logged_in?
!!session[:customer_id]
end
And in my view am trying to access the application_controller action like this
<% unless is_customer_logged_in? %>
some functions
<% end %>
The above code is a partial layouts.
This is the error message I am facing
undefined method `is_customer_logged_in?' for #<#<Class:0xb51a5300>:0xb5616484>
You can define it to be a helper method and you should be able to access that method in the view.
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def is_customer_logged_in?
!!session[:customer_id]
end
helper_method :is_customer_logged_in?
end
try helper_method: is_customer_logged_in?
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.
orry for the basics, but I'm having a hell of a time getting a very basic flow to work:
1) Define module with a method to save a url to a var (or return it)
2) Call that method in a controller to initialize the method
3) Have a view show that URL
NoMethodError in AuthController#oauth undefined method `oauthurl' for GetAccessToken:Module
Module: \lib\get_access_token.rb
module GetAccessToken
CONSUMER_TOKEN = { :token=>"mytokenstringwhichisreallylong", :secret=> "mysecretstringwhichisreallylong" }
def self.oauthurl
#oauthurl="https://us.etrade.com/e/t/etws/authorize?key=#{(CONSUMER_TOKEN[:token])}&token="
end
end
Controller: app\controllers\auth_controllers.rb
require 'get_access_token'
class AuthController < ApplicationController
include GetAccessToken
before_filter :oauthurl1
def oauthurl1
GetAccessToken.oauthurl
end
end
View: app\views\auth\oauth.html.erb
<% provide(:title, 'oAuth') %>
<h1>oAuth</h1>
<%= link_to "oAuth", #oauthurl %>
My higher level goal is to get the eTrade oAuth flow working, but I want to make sure I understand every line of code vs. taking someone else's and I can't get this very basic building block to work yet.
Add the following to config/application.rb:
config.autoload_paths += Dir["#{config.root}/lib/**"]
Change your AuthController to:
class AuthController < ApplicationController
include GetAccessToken
def oauthurl1
GetAccessToken.oauthurl
end
end
Your module code will be
module GetAccessToken
CONSUMER_TOKEN = { :token=>"mytokenstringwhichisreallylong", :secret=> "mysecretstringwhichisreallylong" }
def self.oauthurl
"https://us.etrade.com/e/t/etws/authorize?key=#{(CONSUMER_TOKEN[:token])}&token="
end
end
and your controller code should be
require 'get_access_token'
class AuthController < ApplicationController
include GetAccessToken
def oauthurl1
#oauthurl = GetAccessToken.oauthurl
end
end
We need to initialize #oauthurl in the controller to use this variable in the view, else it will be nil.
With the generous help of the contributions above, this is how I finally resolved the error. I defined the instance variable in the controller instead of the model, and initialized the controller method using before_filer:
Model:\lib\test_module.rb
module TestModule
CONSUMER_TOKEN = { :token=>"myReallyLongToken", :secret=> "myReallyLongSecret" }
def self.testUrl
"https://us.etrade.com/e/t/etws/authorize?key=#{(CONSUMER_TOKEN[:token])}&token="
end
end
Controller: app\controllers\test_controller.rb
require 'test_module'
class TestController < ApplicationController
include TestModule
before_filter :testUrl1Init
def testUrl1Init
#testurl=TestModule.testUrl
end
end
View: \app\views\test\test.html.erb
<% provide(:title, 'test') %>
<h1>test</h1>
<%= link_to "test link", #testurl %>