Allow unauthenticated users to access views that utilize current_user - ruby-on-rails

I have lots of views that have elements that check if the current user isn't the same user that's being viewed, etc. For example, on the user show page there is a button that allows a user to follow another user, which doesn't appear if the user is looking at their own profile.
<% if current_user != #user %>
<div id="follow_form">
<% if current_user.following?(#user) %>
<%= render 'users/unfollow' %>
<% else %>
<%= render 'users/follow' %>
<% end %>
</div>
<% end %>
The problem arises that if you're not logged in, rails throws an error.
undefined method `id' for nil:NilClass
<% if current_user.id == #user.id %>
<%= link_to "Edit Profile", edit_user_registration_path(#user) %>
<% else %>
<%= link_to 'message', new_message_path(receiver_id: #user.id) %>
...
I don't want to have to force people to log in or sign up to view index or show pages. How can I get around this?

You should try that:
<% if user_signed_in? %>
<% if current_user != #user %>
<div id="follow_form">
<% if current_user.following?(#user) %>
<%= render 'users/unfollow' %>
<% else %>
<%= render 'users/follow' %>
<% end %>
</div>
<% end %>
<% end %>

Related

How to display related items

I want to display related experiences below the local experiences. I tried to do it using #experiences= Experience.excludes(house.experiences) but didnt work out. Can I get any suggestion how to do that.
<h3>Local experiences</h3>
<section class="list-box">
<% #house.experiences.each do |experience| %>
<p>
<%= experience.name %>
<% if logged_in? && current_user.role == "customer" %>
<%= link_to "Make Enquiry", new_message_path(receiver_id: experience.supplier.user) %>
<% else %>
<%= link_to "Make Enquiry", new_customer_path %>
<% end %>
</p>
<% end %>
</section>
<h3>Related experiences</h3>
<section class="list-box">
<% #experiences.each do |experience| %>
<p>
<%= experience.name %>
<% if logged_in? && current_user.role == "customer" %>
<%= link_to "Make Enquiry", new_message_path(receiver_id: experience.supplier.user) %>
<% else %>
<%= link_to "Make Enquiry", new_customer_path %>
<% end %>
</p>
<% end %>
</section>
There is no method called excludes in the rails model. There is only exclude?, which is a instance method of class String. Refer here.
For your issue, maybe something like below would work given that house_id is the foreign_key in your experience table.
#experiences = Experience.where.not(house_id: house.experiences)
You may refer here for more not conditions.

conditional in users/show page to display info or not based users having created it

This is the error I get:
Showing /home/ubuntu/workspace/UMUV/app/views/users/show.html.erb where line #6 >>raised:
undefined method `name' for nil:NilClass
This is my conditional in users/show:
<% if #profile_info.present? %>
<%= #profile_info.region.name %>
<% else %>
<%= #user.email%>
<% end %>
This is in the users/controller:
def show
#user = User.find(params[:id])
#profile_info = Profile.find_or_initialize_by(user_id: params[:id])
end
I basically want to know how to not have an error when i visit a user's profile page and the user hasn't updated their profile yet. Showing the page is working fine if i update the user's profile through "edit page" manually.
Please help with the conditional. I also have a feeling i can create method in user.rb or users/controller, but really dont know how to implement this conditional to do what i want it to.
Thank you
In your show page you can replace this :
<% if #profile_info.present? %>
<%= #profile_info.region.name %>
<% else %>
<%= #user.email%>
<% end %>
with this:
<% if #profile_info.present? %>
<%= #profile_info.region.try(:name) %>
<% else %>
<%= #user.try(:email)%>
<% end %>
and also go through this post: http://everydayrails.com/2011/04/28/rails-try-method.html
Well you can always test an initalized object vs a saved object using new_record? -- which would make your above view look more like:
<% if #profile_info.new_record? %>
<%= #user.email%>
<% else %>
<%= #profile_info.region.name %>
<% end %>
also you might be able to take advantage of try on part of your page, which fails gracefully if an attribute doesn't exist, like
#profile_info.region.try(:name)
Since your error is with the name #profile_info.region.name not being present you could change your conditional to:
<% if #profile_info.region.name.present? %>
<%= #profile_info.region.name %>
<% else %>
<%= #user.email%>
<% end %>
Or if you really want to test #profile_info.present? you could nest conditionals like this:
<% if #profile_info.present? %>
<% if #profile_info.region.name.present? %>
<%= #profile_info.region.name %>
<% end %>
<% else %>
<%= #user.email%>
<% end %>
I hope that helps!

Check if Spree Cart is empty

How can I check if the Spree cart is empty, so I can change the button if it isn't?
I thought there was a method line_items.count...
<% unless line_items.count > 0 %>
<%= link_to "<button>Empezar Pedido</button>".html_safe, "/shop" %>
<% else %>
<%= link_to "<button>Terminar Pedido</button>".html_safe, "/shop" %>
<% end %>
Thanks!
This is very simple I solved my this problem like this
In application_controller.rb
def load_cart
#order = current_order
end
In frontend in you case
<% unless #order.line_items.count > 0 %>
<%= link_to "<button>Empezar Pedido</button>".html_safe, "/shop" %>
<% else %>
<%= link_to "<button>Terminar Pedido</button>".html_safe, "/shop" %>
<% end %>
Thanks

How do I check CanCan abilities on an object in a `shared/partial`?

Per the CanCan documentation, to check if a user has the ability to do something to any element in the view, you do something like this:
<% if can? :create, #project %>
<%= link_to "New Project", new_project_path %>
<% end %>
Or you can check with the class like:
<% if can? :create, Project %>
<%= link_to "New Project", new_project_path %>
<% end %>
In my case, I have a DashboardController#Index, that has this:
#nodes = current_user.nodes.where(:is_comment => nil)
In my views/dashboard/index.html.erb, I have this:
<% #nodes.each do |node| %>
<!-- Upload Video Comment Popup -->
<div class="box">
<%= render partial: "shared/comments", locals: {node: node} %>
</div>
<% end %> <!-- node -->
Then in my shared/_comments.html.erb, I have this:
<% if node.comments.present? %>
<% node.comments.each do |comment| %>
<% if can? :manage, Comment %>
Show Something Interesting Here
<% else %>
Show something boring here
<% end %>
<% end %>
<% end %>
That doesn't work.
I also tried this:
<% if node.comments.present? %>
<% node.comments.each do |comment| %>
<% if can? :manage, comment %>
Show Something Interesting Here
<% else %>
Show something boring here
<% end %>
<% end %>
<% end %>
And that doesn't work either.
This is my ability.rb
can :manage, Comment, user_id: user.id
I thought about creating a #comments instance variable in the controller, but the issue with that is that the comments are on a collection of nodes (i.e. I need to show multiple nodes, and each node has multiple comments).
How do I approach this?
Your last code should work after updating to CanCanCommunity version of cancan
<% if node.comments.present? %>
<% node.comments.each do |comment| %>
<% if can? :manage, comment %>
Show Something Interesting Here
<% else %>
Show something boring here
<% end %>
<% end %>
<% end %>
related to How do I show an error for unauthorized can can access

notices and errors on rails3

I read somewhere that rails 3 form helper does not have error messages embedded in it anymore. I am wondering how I am supposed to show flash messages when I set them up inside my controller or as an inline notice in redirect_to? How am I supposed to display them on my view? Is there helper for this?
For example if I have
def update
if #person.save
flash[:notice] = "Successfully saved!"
end
end
how do i show the notice on my view?
flash will still work as long as you display it in your layouts:
<div id="page">
<% if flash[:alert] %>
<p class="flash-error"><%= flash[:alert] %></p>
<% end %>
<% if flash[:notice] %>
<p class="flash-notice"><%= flash[:notice] %></p>
<% end %>
<%= yield %>
</div>
You can either display error messages manually or use the dynamic_form gem which gives you the old behavior.
You can still display flash messages in your view with this:
<%= flash[:notice] %>
But if you want to display for error messages:
#In your form
<%= form_for #foo do |f| %>
<%= render "shared/error_messages", :target => #foo %>
...
<% end %>
#shared/_error_messages.html.erb
<% if target.errors.any? %>
<div id="error_explanation">
<ul>
<% target.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>

Resources