run coffeescript if user is present - ruby-on-rails

I'm trying to find a way to only run a specific piece of coffeescript code if the user is signed in. Is there a way to achieve this without having to include that specific coffeescript file. For example check if a session cookie with the value of user_id is found, then run this piece of code.
The goal is to remove some inline javascript and move them over to the assets.

Rails by default uses ActionDispatch::Session::CookieStore so theoretically you could read the cookie and get the user id. However to avoid spoofing and session based attacks the cookie is encrypted. And you can't decrypt it without exposing the Rails secret_key_base to the client - which is a really bad idea or forgoing the protection of encrypted cookies.
Instead might just want to let your view / layout tell you if there is a signed in user:
<!DOCTYPE html>
<html>
<head>
<title>Chess</title>
<%= stylesheet_link_tag 'application', media: 'all' %>
<%= javascript_include_tag 'application' %>
<%= csrf_meta_tags %>
</head>
<%= content_tag(:body, data: { "signed-in" => user_signed_in?.to_s }) do %>
<%= yield %>
<% end %>
</html>
This will let you read $('body').data('signed_in') and avoids exposing / duplicating any of the actual authentication logic on the client. This also works well with Turbolinks since Turbolinks replaces the body tag.
You would use it like so:
// #return Boolean
function is_user_signed_in(){
$('body').data('signed-in') === 'true';
}

You can move your javascript out to assets.
Expanding on max's answer, it can then look at the value of $('body').data('signed_in')
for example:
if($('body').data('signed_in') == true){
//execute
}
So your javascript still needs to be included in the client's browser but using some logic like that above allows you to only run if there is a user signed in.

Related

include a javascript file only on signup page - Rails & Turbolinks

I need to include a JS file only on the signup page of my rails application. I am using Turbolinks.
I have the below code in application.html.erb just before the <head> section
<%= yield :page_specific%>
and below is the code in my registrations/new.html.erb
<%content_for :page_specific do%>
<%= javascript_include_tag 'page_specific/users/registrations/index', 'data-turbolinks-track' => true%>
<%end%>
This works as expected and loads the script on the registrations page, but if I visit the login page from registrations page, the script remains included in the head section as i have turbolinks enabled.
How can include a page specific javascript only on signup page with turbolinks enabled.
Not sure if its the most elegant way but I managed to fix the issue by disabling turoblinks on login and sign up link by using :'data-turbolinks' => "false"
Hope it helps. Thanks.
Just include javascript_include_tag into view of target page

How to safely store Google Api keys with rails and use them in scripts?

I'm trying to safely store the Google api key that I'm using in a rails project. I tried storing it in a my secrets.yml file but if I then say in my google script &key=ENV['google_api'], it can't fetch it.
I'm pretty sure this is not the way but after googling the topic, I can't really find a clear answer on this. Anyone who can offer some help?
Thanks,
Thomas
UPDATE, here's the code I'm using to fetch the key in my layouts file:
Issue, I'm still receiving the error that my api_key is "nil".
<script>
var GOOGLE_API_KEY="#{ENV['GOOGLE_API_KEY']}"
</script>
<%= javascript_include_tag "//maps.google.com/maps/api/js?v=3.23&key=#{ENV['GOOGLE_API_KEY']}&libraries=geometry,places&language=&hl=&region=&callback=initMap"%>
You will want to put the script call in your application.html.erb file so ruby can parse the ENV['google_api']. Here is an example application file (in HAML):
!!!
%html
%head
%title Pursuit
= stylesheet_link_tag 'application', media: 'all'
= csrf_meta_tags
:javascript
var GOOGLE_API_KEY="#{ENV['GOOGLE_API_KEY']}"
= javascript_include_tag 'application'
= javascript_include_tag "//maps.googleapis.com/maps/api/js?libraries=places&key=#{ENV['GOOGLE_API_KEY']}"
%body
= render 'layouts/menu'
.row
.col.m12.l10.offset-l1
= yield
I was using the figaro gem. For me worked adding the environmental variable to application.yml file.
GOOGLE_API_KEY: there_put_the_key
Then on top of the
app/views/layouts/application.html.erb
(If you want to add source to all of views else you can add this line to specific view) simply add this line
<%= javascript_include_tag "//maps.google.com/maps/api/js?key=#{ENV['GOOGLE_API_KEY']}" %>

Setting up meta data for a Rails Website

I have been struggling to figure out how to place my meta data for all pages. The head tag where the meta data must be placed is on application.html.erb. My approach at first which I later found as a bad practice was to check the URL path, like: if request.original_fullpath == '/faq' to show the meta data for the FAQ page.
Despite being a bad practice, this couldn't help on pages that are dynamic (like the user's profile pages). Then I decided to take a simple approach and make it work. I added the meta tags on each page individually. I was naive thinking that can be overridden by using the head tag on each page. So I was wondering, how do I set the meta tags/data for each page on Rails? What's your approach?
The content_for helper might work well.
# app/views/layouts/application.html.erb
<head>
<%= content_for :meta_tags %>
</head>
# app/views/posts/show.html.erb
<% content_for :meta_tags do %>
...
<% end %>

Rails 3.2.15 "Can't verify CSRF token authenticity" although token exists

I have a form_tag with remote: true. It is for members subscription in newsletter.
I have the "csrf_meta_tags" in my layout. When I submit the form I get the "Can't verify CSRF token authenticity" Warning. I want to mention that the csrf_token exist both in the layout and form.
I could not find a good answer on this.
I this when JS is disabled? I usually have this problem, and including authenticity_token: true in the form tag solved it for me. The docs explain it better.
:authenticity_token - Authenticity token to use in the form. Use only if you need to pass custom authenticity token string, or to not add authenticity_token field at all (by passing false). Remote forms may omit the embedded authenticity token by setting config.action_view.embed_authenticity_token_in_remote_forms = false. This is helpful when you’re fragment-caching the form. Remote forms get the authenticity from the meta tag, so embedding is unnecessary unless you support browsers without JavaScript.
I had the same problem. I was able to fix it by adding back my turbolinks stylesheets and javascripts.
Try adding to application.html.erb head tag:
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>

Check in view what page the user is on

Is there any way in Rails to check which page a user is currently viewing?
my example: In the head section of my website I need to know if a user has opened a blog post. If a user is viewing a post then in the head section facebook open graph meta tags need to be added because user has the option to like the blog post.
It would be invaluable if someone could help me with this.
As other answers mention you can check current page by examining request object or params hash.
But there is better way to set up Facebook meta tags without explicitely checking page context. content_for helper method is a perfect hit here. See the docs here: http://api.rubyonrails.org/classes/ActionView/Helpers/CaptureHelper.html#method-i-content_for
Basically, content_for takes a block as argument and captures the output which can be displayed elsewhere with yield.
So you can capture some content in your views:
# index.html.erb (blog index)
<% content_for :facebook_meta do %>
<meta content='My blog' property='og:site_name'>
...
<% end %>
# show.html.erb (single blog post)
<% content_for :facebook_meta do %>
<meta content='<%= #post.title %>' property='og:site_name'>
...
<% end %>
And display them in layout:
# application.html.erb (application layout)
<html>
<head>
<%= yield :facebook_meta %>
</head>
</html>
The above is much cleaner than checking current controller/action in this scenario. You only define Facebook meta tags in places they apply to.
With help from Radar in the #RubyOnRails IRC channel, I used the following code:
params[:action] and params[:controller]
You can check all the context of the request (action, controller, headers...) using the request helper that is available in the controller
http://api.rubyonrails.org/classes/ActionDispatch/Request.html

Resources