How to get user's photos in a general view - ruby-on-rails

I'm trying to make an alert that shows up in every view (I've put it in application.html.erb), that only shows up if the user (current_user) hasn't uploaded any photo yet.
The thing is, I don't know how to put my controllers in order to retrieve user.photos and check if it's blank.
In my view
<% if #user.photos.blank? %>
<div class="alert-header">
<i class="icon-cog green"> </i> Todavía no has subido ningún spot
<button class="semi_margin_left smallbutton medium"> Sube uno </button>
</div>
<% end %>
I've tried to put in my pages controller:
#user = current_user
#photos = #user.photos
It will give me an error when doing logout.
The question is, what controller do I need to touch if I want #user.photos to be available in all of the app? The alert is going to show up in the whole app.
Thanks

Add helper method to application controller:
# application_controller.rb
before_action :check_photos_alert
def check_photos_alert
#show_photo_alert = #user && #user.photos.blank?
end
Just make sure that #user is being set before this action is being invoked. Then in your view you can check whether #show_photo_alert flag is set.
<% if #show_photo_alert %>
<div class="alert-header">
<i class="icon-cog green"> </i> Todavía no has subido ningún spot
<button class="semi_margin_left smallbutton medium"> Sube uno </button>
</div>
<% end %>
One point to note though: ApplicationController is a parent class for most if not all of your controllers so it might be too much to perfom this check on every request. If such is the case, move this logic from ApplicationController to a module and include this module to every controller you need this check.

Related

has_scope filter by cost feature [Ruby]

I need to set up a feature where the index page of freelancers can be filtered to only display based on a range on the attribute of price. This needs to be done from the user side, i was thinking two input boxes and a submit button.
How do I go about doing this? I checked out the has_scope gem, but I'm worried it's going to mess up my already defined order of freelancers, where they are ordered by the attribute featured (boolean). Essentially the order of the freelancers must stay the same, but then a filter must be added to that ordered object, to only show the freelancers in that price range.
There must be a way to do this but I'm very unsure. I'm going to do a bit of a code dump below, can someone point me in the right direction and show me how?
class HomeController < ApplicationController
before_action :set_freelancer, only: %i[ show edit update destroy ]
def index
#pagy, #freelancers = pagy(Freelancer.order(featured: :desc))
end
private
# Use callbacks to share common setup or constraints between actions.
def set_freelancer
#freelancer = Freelancer.find(params[:id])
end
end
My home controller
<% if user_signed_in?%>
<%== pagy_nav(#pagy)%>
<div class="d-flex flex-wrap justify-content flex-shrink-1 gap-3">
<%#freelancers.each do |freelancer| %>
<div class="card mb-3" style="max-width: 540px">
<div class="row g-0">
<div class="col-md-4">
<img src="https://i.pinimg.com/originals/57/f5/da/57f5da08bd8f52bc2d3e4ebadd67b642.jpg" class="img-fluid rounded-start" alt="6-logo">
</div>
<div class="col-md-8">
<div class="card-body">
<%= render freelancer %>
<%= link_to "Show this freelancer", freelancer, class: "btn btn-info" %>
</div>
</div>
</div>
<br/>
</div>
<%end%>
<% else %>
<h1>Please sign up, or sign in!</h1>
<%end%>
My webpage outputting each freelancer, ive also added my github itself below, im aware ive asked alot for help lately here but i am learning alot so i appreciate it
https://github.com/LCzoboriek/freelancer-assignment
(UPDATE)
So ive now added this code below to my home_controller.rb
def index
freelancers_scope = Freelancer.order(featured: :desc)
freelancers_scope = freelancers_scope.where("cost >= ?", params[:cost_lower_than]) if params[:cost_greater_than].present?
freelancers_scope = freelancers_scope.where("cost <= ?", params[:cost_greater_than]) if params[:cost_lower_than].present?
#pagy, #freelancers = pagy(freelancers_scope)
end
and this to my views, but its throwing an error saying undefined local variable or method `index' for #ActionView::Base:0x00000000013178. How do i point my form to that freelancers_scope part in my controller?
<%= form_for(index) do |f| %>
<%= f.input :cost_greater_than%>
<%= f.input :cost_lower_than%>
<%= submit_tag("Submit") %>
<% end %>
i was thinking two input boxs and a submit button.
this sounds absolutely fine
this is a very basic thing and you don't really need a gem for that, how about:
def index
freelancers_scope = Freelancer.order(featured: :desc)
freelancers_scope = freelancers_scope.where("cost >= ?", params[:cost_greater_than]) if params[:cost_greater_than].present?
freelancers_scope = freelancers_scope.where("cost <= ?", params[:cost_greater_than]) if params[:cost_lower_than].present?
#pagy, #freelancers = pagy(freelancers_scope)
end
if you really want a scope you could later define it in the Freelancer model so you wouldn't have to call where directly in the controller

Rails: show.modal on a index.each form

I have and index page showing a list of users. What I want is for when I click on a link_to show a certain user in that #users.each form, that shows up the modal (pop ups fine) but gives the data of that user in it as well.
users/index.html.erb
<div class="container">
<% #users.each do |user| %>
<%= link_to user.name, user, { remote: true, "data-target": "#modal-full" } %>
<% end %>
</div>
<%= render 'layouts/modalfull' %>
layouts/_modalfull.html.erb
<div id="modal-full">
<h1 class="name"></h1>
</div>
UsersController
def show
#user = User.find(params[:id])
redirect_to do |format|
format.js // because that would be where the js code would be to push the data to the modal, right?
end
end
Now how it should go in the in the show.js.erb, I have no idea, I'm really not familiar with those stuffs, still new with Rails.
So right now, what I did, will pop-up the modal but wouldn't send the data from the user I clicked on. And I believe that's on the JavaScript side > show.js.erb.
Continued trying different things and came up with this, which made it work.
Which is partially an answer, you'll know why bellow.
users/show.js.erb
$("#modal-full .name").html("<%= #user.name %>");
But if there is any cleaner way to do this, please share.
Because right now, the thing works, it replaces the name but, we see the change being made. So if I clicked on a John, modal would pop up with "John" written on it. Then I close it and click on "Jennifer", modal will pop up with "John" and takes a second to change it to "Jennifer".

Rails Navbar application controller variable

I have a value that I use inside the navbar. Think of it as some sort of low skill notification. On the root page I have access to it because I define it inside that method:
#conversations = Conversation.where("sender_id = ? OR recipient_id = ?",current_user.id,current_user.id)
If I move to a different method(page), the scope of that variable will be out and I'd have to redefine it again.
How can I define this variable as a cross-controller variable as every page has the same navbar?
<li> Conversations <%= #conversations.count %> </li>
ApplicationController
....
before_action: :conversation_count
def conversation_count
#conversations =
Conversation.where("sender_id = ? OR recipient_id = ?",current_user.id,current_user.id) if current_user.present?
end
...
Navbar Show count only if user is loggedin
<ul>
<li> About </li>
<% if current_user.present %>
<li>Conversations <%= #conversations.count %></li>
<% end %>
</ul>
Navbar Show count irrespective of user is logged in or no
<ul>
<li> About </li>
<li>Conversations <%= #conversations.try(:count).to_i %></li>
</ul>
You need to place the navbar in the layouts/application.html.erb and the rest of the content by calling the yield block so you are actually not changing the navbar based on controller(It is fixed).
Also assign the variable in the application_controller's method so as to access it throughout the other controllers.
If current_user is not accessible from application_controller may be you have to restart your server(but usually it is accessible).
use
if current_user.present?
instead of
if current_user.present
question mark is missing
As someone else said, current_user works in application controller.
If you copy and paste whatever code you have from your conversations controller to your application controller, you'll have access to it from every controller than inherits from application controller (all of them unless you specify otherwise).

view reviews of a book using conditional logic to determine which reviews to display

I am making a book review/online book group app.
On the individual book show page, I would like to have the user decide whether or not they would like to see reviews, reviews with spoilers or all of it. Therefore when the page loads they should see only the main info about the book, and three buttons: See Reviews, See Spoilers, See All.
Now this seems like it should be a totally easy task. If I were using JS and jQuery, I would just hide all the elements and have the buttons trigger jQuery shows if they match the objects spoiler code, however this does not work in Rails.
I have tried doing js in the view, I have tried running the logic through their own routes, I've tried functions in the controller and helper and nothing works!! Auuugghh! I've been working on this for almost 2 days and want to smash my computer in. Granted, this is my first project back on Rails after 6 months off, I've been working mostly in Node, and my Rails is rusty. Here's the code that may be pertinent, but it's Rails so it's all over the place so it might just be easier to look at the github repo, which is here. https://github.com/nwimmer123/readit_rails
I've been cruising StackOverflow and reading APIDock, but haven't been able to figure this out. Any help would be greatly appreciated.
show.html.erb
<div class="container">
<%= button_to "Show Reviews", class: "btn btn-primary col-xs-2" %>
<%= button_to "Show Spoilers", class: "btn btn-primary col-xs-2" %>
<%= link_to "Show It All", controller: "books", method: "find_reviews", class: "btn btn-primary col-xs-2"%>
</div>
<% if #show_the_reviews == true %>
<div class="container">
<% #reviews.each do |review| %>
<% if review.book_id.to_s == params[:id].to_s %>
<div class="review">
<div>
<strong><%= review.user.name %></strong>
<% if review.spoiler == "1" %>
<span class="center-text">SPOILER</span>
<% end %>
</div>
<p><%= review.body %></p>
<button class="pull-right">Respond</button>
</div>
<% end %>
<% end %>
</div>
<% end %>
</div>
books controller
def show
#user = current_user
#reviews = Review.all
end
private
def book_params
params.require(:book).permit(:title, :author, :genre, :image, :publication_date, :publisher, :synopsis)
end
def current_book
#book = Book.find_by_id(params[:id])
end
def find_reviews
puts "LOOK HERE!!!!!!"
#reviews.each do |review|
if review.book_id.to_s == params[:id].to_s
puts review.spoiler
end
end
#show_the_reviews = true
redirect_to book_path(#book.id)
end
end
When I click Show It All, it redirects to home page?!
Note, I realize this question is poorly written and vague, but I'm super annoyed and can't figure out how to write it better. I think I'm looking for basic strategies here.
You can do it easily with jQuery, just give the reviews an appropriate class..
<% review_class = review.spoiler == true ? ' spoiler' : ' spoiler-free' %>
<div class="review <%= review_class%>">
Then put some <script> at the top of the view that will toggle show/hide for $('.spoiler') and $('.spoiler-free') and have your buttons onclick call the js functions.
You can do it in pure rails by making a field-less form with submit buttons, and in the called action test params[:commit] which will have the text of the button that was clicked, and then use that in conditional logic to filter out whether you retrieve spoiler reviews, non-spoiler reviews, or both. But the jQuery is way more responsive.

Rails: Dropdown with links to show pages

I am trying to put a drop down in my navbar where users can click on links to the different stone show pages. With the code I have in now I am getting a NoMethodError private method `each' called for nil:NilClass.
I am pretty sure this private method error is coming up because I am putting this code in my navbar which is in my application.html.erb rather then in the stone model. Could someone point me in the right direction as to where I should define methods for the navbar? Or if there is something else I should be doing instead?
Here is what I have attempted so far:
application.html.erb
<div class="dropdown">
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Dropdown Example
<span class="caret"></span></button>
<ul class="dropdown-menu">
<% #stones.each do |stone| %>
<li> <%= link_to stone_url do %>
<%= stone.name %>
<% end %>
</li>
<% end %>
</ul>
</div>
application_controller.rb
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
helper_method :current_order
def each
#product = Product.all
end
def current_order
if !session[:order_id].nil?
Order.find(session[:order_id])
else
Order.new
end
end
end
you are calling .each on the var #stones and not on your controller, views cant call methods from controllers, unless they are helper methods. try to use a before_filter in your controller that will set your #stones and remove that each method from the controller
Just replace #stones.each to Stone.all.each.
Because there will be somewhere using var #stones, you should not define #stones on your application_controller.rb.

Resources