Rails 4 - Messenger gem - tutorial setup - ruby-on-rails

I am trying to make an app in Rails 4.
I'm trying to follow this tutorial to setup the messenger gem. http://josephndungu.com/tutorials/private-inbox-system-in-rails-with-mailboxer
I have:
Gemfile:
gem "mailboxer"
User.rb
def mailboxer_name
self.full_name
end
def mailboxer_email(object)
self.email
end
mailboxer.rb initialiser
config.email_method = :mailboxer_email
config.name_method = :full_name
I have an attribute in my user table called :email and I have a method in my user model called:
def full_name
if first_name.present?
[*first_name.capitalize, last_name.capitalize].join(" ")
else
test full name
end
end
One difference between this attempt and the tutorial is that since I previously tried the site point tutorial (and couldn't get it working), I already have a messages controller and view folder in my app. Where this tutorial users 'mailbox', I use 'messages'
I can't get past the first test point in this tutorial. I get this error:
NoMethodError in MessagesController#inbox
undefined method `inbox' for #<ActiveRecord::Associations::CollectionProxy []>
The error message highlights this method:
def inbox
#inbox = messages.inbox
#active = :inbox
end
I have:
messages controller
class MessagesController < ApplicationController
before_action :authenticate_user!
def inbox
#inbox = messages.inbox
#active = :inbox
end
def sent
#sent = messages.sentbox
#active = :sent
end
def trash
#trash = messages.trash
#active = :trash
end
end
application helper
def flash_class(level)
case level.to_sym
when :notice then "alert alert-success"
when :info then "alert alert-info"
when :alert then "alert alert-danger"
when :warning then "alert alert-warning"
end
end
def active_page(active_page)
#active == active_page ? "active" : ""
end
messages helper
def unread_messages_count
# how to get the number of unread messages for the current user
# using mailboxer
messages.inbox(:unread => true).count(:id, :distinct => true)
end
messages views folder has:
_folder_view.html.erb
<div class="row">
<div class="spacer"></div>
<div class="col-md-12">
<!-- we'll configure this to compose new conversations later -->
<%= link_to "Compose", "#", class: "btn btn-success" %>
<div class="spacer"></div>
</div>
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-body">
<%= render 'messages/folders' %>
</div>
</div>
</div>
<div class="col-md-8">
<div class="panel panel-default">
<div class="panel-body">
<!-- individual conversations will show here -->
</div>
</div>
</div>
</div>
view raw
_folders.html.erb
<ul class="nav nav-pills nav-stacked">
<li class="<%= active_page(:inbox) %>">
<%= link_to messages_inbox_path do %>
<span class="label label-danger pull-right"><%=unread_messages_count%></span>
<em class="fa fa-inbox fa-lg"></em>
<span>Inbox</span>
<% end %>
</li>
<li class="<%= active_page(:sent) %>">
<%= link_to messages_sent_path do %>
<em class="fa fa-paper-plane-o fa-lg"></em>
<span>Sent</span>
<% end %>
</li>
<li class="<%= active_page(:trash) %>">
<%= link_to messages_trash_path do %>
<em class="fa fa-trash-o fa-lg"></em>
<span>Trash</span>
<% end %>
</li>
</ul>
each of inbox.html.er, sent.html.erb and trash.html.erb
<%= render partial: 'messages/folder_view' %>
routes.rb
get "messages/inbox" => "messages#inbox", as: :messages_inbox
get "messages/sent" => "messages#sent", as: :messages_sent
get "messages/trash" => "messages#trash", as: :messages_trash
Application controller:
helper_method :messages
private
def messages
#messages ||= current_user.messages
end
Can anyone see where I've gone wrong?
I'm up to tutorial step that says: Clicking the inbox link should take you to our up and running inbox page with navigation already in place for the inbox, sent and trash folders.
Instead, I get an error message that says:
NoMethodError in MessagesController#inbox
undefined method `inbox' for #<ActiveRecord::Associations::CollectionProxy []>
Can anyone see what's wrong?

You've forgot to add helper method messages to ApplicationController as it made in tutorial:
class ApplicationController < ActionController::Base
# [...]
helper_method :messages
private
def messages
#messages ||= current_user.mailbox
end
protected
# [...]
end
Update 1
I see that in your helper you have current_user.messages in should be current_user.mailbox

Related

NoMethodError in Orders#show , undefined method `grand_total' for nil:NilClass

I'm want to show the grand_total to the show page and i have do a partial file to put in the table, in inside i want to grab the orderproduct data and show to front , but it show me this error. It seem like i didn't define method grand_total, but not sure how to solve it.
Orders controller
class OrdersController < ApplicationController
def supplier
#supplier = Supplier.find(params[:id])
end
def outlet
#outlet = Outlet.find(params[:id])
end
def index
#orders = Order.all
end
def show
#orders = Order.all
#order_products = OrderProduct.all
end
def new
#order = Order.new
#supplier = Supplier.all
#outlet = Outlet.all
#products = Product.all
end
def create
#order = Order.new(order_params)
#supplier_id = Supplier.all
#outlet_id = Outlet.all
if #order.save
product_ids = params[:product_ids]
product_ids.each do |product_id|
OrderProduct.create(order_id: #order.id, product_id: product_id)
end
flash[:success] = "Succesful create!"
redirect_to #order
else
render 'new'
end
end
private
def order_params
params.require(:order).permit(:supplier_id,:quantity, :grand_total, :order_date,
:delivery_date, :delivery_address, :outlet_id)
end
end
_orderproduct.html.erb
<div class="container">
<ul class="responsive-table">
<li class="table-header">
<div class="col col-1">Product</div>
<div class="col col-2">Price</div>
<div class="col col-4">Grand_total</div>
</li>
<% #order_products.each do |order_product| %>
<li class="table-row">
<div class="col col-1" data-label="Product"><%= order_product.product.name %></div>
<div class="col col-2" data-label="Price"><%= order_product.product.price %></div>
<div class="col col-4" data-label="Grand_total"><%= order_product.order.grand_total %></div>
<% end %>
</ul>
</div>
show.html.erb
<% provide(:title)%>
<h2 class="dashboard">Order details</h2>
<div class="row">
<aside class="col-md-4">
<section class="stats">
<%= render 'shared/stats' %>
</section>
<%= render 'orders/orderproduct' %>
<div class="side">
<button class="button-30"><%= link_to "Back to home", home_path %></button>
</div>
</aside>
</div>
Error show in website
The only place in your examples on which you call grant_total is this:
<%= order_product.order.grand_total %>
The error message tells that there is a NoMethodError in Orders#show, undefined method grand_total for nil:NilClass. This means you are calling grant_total on something that is nil and not the type of object you expect. This can only happen when order_product.order returned nil. And that means you have an order_product in your database that doesn't have an order assigned.
There are several ways to fix that, depending on what you want to achieve:
add a validation that ensures that all order_products have an order assigned.
backfill missing orders in the database
exclude order products without associated order when loading or
checking if there is an order and only then outputting its grant total
you can use debugger to see which variable is returning nil value.
Check and work from there.

Displaying search bar query results from an API in Rails

I am trying to create a simple app where you find games from an API via a search bar. I am using the Giant Bomb API gem (https://github.com/games-directory/api-giantbomb). The gem seems to be working since I can call things via the console. However, I am not quite sure how to display results or if there are problems with my search method (likely).
Here is my controller for Games:
class GamesController < ApplicationController
//Display search results
def index
#games = Game.all.order('created_at DESC')
#games = #games.search(params[:query]) if params[:query].present?
end
//Searches through API and redirects to results on index.
def search
#games = GiantBomb::Search.new().query(params[:query]).resources('game').limit(5).fetch
redirect_to index_path
end
private
def game_params
params.require(:game).permit(:name)
end
end
My search bar code on my home page:
<div class="search-font"><h1>Build your Collection</h1></div>
<div class="container">
<div class="row">
<div class="col-md-12">
<%= form_tag search_path class: "row", method: :get do %>
<div class="col-12 col-sm pr-sm-0">
<%= text_field_tag :game,
params[:game],
class: "form-control input-lg",
id: "typed-text" %>
</div>
<div class="input-group-btn ml-3">
<%= submit_tag "Search", class: "btn btn-primary" %>
</div>
<% end %>
</div>
</div>
</div>
And my index.html.erb where it is supposed to spit out the game names.
<ul>
<% #games.each do |game| %>
<li><%= game.name %></li>
<% end %>
</ul>
The search bar redirects but nothing is posted. In my console I can do search.query('Mario') then search.fetch to print out the results, but I am not sure how to use this function in my controller correctly.
[edit] Here are my routes as well.
Rails.application.routes.draw do
devise_for :users
resources :games
root to: 'pages#home'
get '/search', to: 'games#search', as: :search
get '/games', to: 'games#index', as: :index
end
redirect_to creates a new request, you need to use render as in...
render 'index'
That way you can use your #games variable in the view

Error 400 when commenting on ruby on rails ecommerce web app

I'm actually making an ecommerce web app which has a User, Category, Book and Comment models. Everything is working nice, but when I try to comment in one of the book, it gives a 400 error. I really need you to help me out. https://github.com/felixpro/Book-app this is my repository.
This is my CommentsController
class CommentsController < ApplicationController
before_action :authenticate_user!
def create
book = Book.find(params[:comment][:book_id])
comment = book.comments.build(comment_params)
comment.user = current_user
​
if comment.save
redirect_to book_path(#book)
end
end
private
def comment_params
params.require(:comment).permit(:body)
end
end
This is the comment view partial,
<% if signed_in? %>
<div class="card bg-light new-comment">
<div class="card-body">
<p class="font-weight-bold">Deja tu comentario:</p>
<%= form_for #book.comments.build do |f| %>
<%= f.hidden_field :book_id, value: #book.id %>
<div class="form-group">
<%= f.text_area :body, rows: 4, class: "form-control" %>
</div>
​
<div class="text-right">
<%= f.submit "Comentar", class: "btn btn-primary" %>
</div>
<% end %>
</div>
</div>
<% else %>
<div class="card bg-light mt-5">
<div class="card-body">
<p class="card-text text-center lead"><%= link_to "Regístrate", new_user_registration_path %> o <%= link_to "Ingresa", new_user_session_path %> para comentar</p>
</div>
</div>
<% end %>
Here are the routes
Rails.application.routes.draw do
devise_for :users
root 'books#index'
resources :books
resources :comments, only: [:create]
end
The error say
This is a pictures showing the error message
The error you mentioned is linked to the fact that you have a special invisible character (non-breaking space) at line 9 and 14 in your CommentsController. This is why you get the
NameError (undefined local variable or method `​' for ...)
This often happens when you hit an additional key at the same time you hit the space bar (cmd + space bar on MacOS). Delete those empty lines and type the enter key again to clear the character.
Then the other answer is right, you'll have have to update your book variable name.
You have referred to #book when the variable is a local book. Use # at the beginning of the line 6:
#book = Book.find(params[:comment][:book_id])

Passing Instance Variables from a Controller to a Layout / .footer?

I am in a dilemma, I'm new and I wonder if you can pass variables to .footer driver, and bootstrap use, chiro display data in a label.
This is the code of the controller:
class JuegosController < ApplicationController
load_and_authorize_resource param_method: :allowed_params, except: [:index, :show]
def index
#juego = Juego.all
end
def show
#juego = Juego.find(params[:id])
end
def new
#juego = Juego.new
end
def create
#juego = Juego.new(allowed_params)
if #juego.save
redirect_to juegos_path
else
render 'new'
end
end
def edit
#juego = Juego.find(params[:id])
end
def update
#juego = Juego.find(params[:id])
if #juego.update_attributes(allowed_params)
redirect_to juegos_path
else
redender 'new'
end
end
def destroy
#juego = Juego.find(params[:id])
#juego.destroy
redirect_to juegos_path
end
private
def allowed_params
params.require(:juego).permit(:id_juego, :nombre, :descripcion, :numero_jugadores, :imagen )
end
end
y este es el codigo del .footer :
<footer class="footer" id="footer-new">
<div class="container-fluid">
<div class="row">
<div class="col-md-3">
<h4>ToyApp</h4>
<p>
<%= link_to 'Inicio', page_path('home') %><br>
<%= link_to 'Acerca de', page_path('about') %><br>
<%= link_to 'Contacto', page_path('contact') %><br>
<%= link_to 'Ayuda', page_path('help') %><br>
<%= link_to 'Términos', page_path('terms') %>
</p>
</div>
<div class="col-md-3">
<h4>Juegos</h4>
<p>
</p>
</div>
<div class="col-md-6" id="bottom-logo-block">
<img src="assets/images/a.png" alt="" width="80" height="80">
<p>
es una marca registrada. Esta prohibido su uso<br>
</p>
<%= link_to 'Políticas de privacidad', page_path('privacy') %>
</div>
</div>
<div class="row">
<div class="col-md-12">
<br>
<p>
xxxxxxxx xxxxxxxxx xxxxxx
</p>
</div>
</div>
</footer>
My question is: how to display the name of a label or h1?
I tried with this but is not work :c
<h1><%= #juego.nombre %></h1>
Help me please, I am newbie.
If the footer is used across the application then you can look at using
content_for / yield
in the footer:
<h1><%= yield :footer_title %></h1>
in the view you can then set the title by controller / action something like
<% content_for :footer_title { #juego.nombre } %>
or
<% content_for :footer_title do %>
Another title
<% end %>
It depends on the context in which the footer is being rendered. If the footer is being rendered within the context of a controller action in which #juego is defined then you should be able to call methods on the object. Two things though.
1) You are defining #juego differently in the different actions. In most of them it refers to a single object, whereas in the index method it refers to a collection of #juego objects. In this context, calling #juego.nombre will almost certainly fail.
2) This is bad practice. If your footer is global (i.e. if it is being shared between different contexts), then you should not be presuming that variable specific to a certain controller is always defined.

Can't link to objects belonging to a category

I have a method that groups all my book categories together
def self.categories_list
joins(:books).
select('categories.id, categories.name, count(*) AS books_count').
group('categories.id, categories.name').
order('books_count DESC')
end
I can then output them to my view like so
#bookcategories = Category.categories_list
What I want to do then is link to all the books belonging to say 'Computing' by clicking 'Computing' in the view
<% #bookcategories.each do |b| %>
<li><%= link_to b.name, category_path(b.name) %></li>
<% end %>
This should take me to my show action of my category controller
def show
#category = Category.where(:name => params[:name]).first
#categorisedbooks = #category.books #get me all books that have the category name
end
and the view for the show action
<div class="container">
<div class="row ">
<div class="span12">
<% #categorisedbooks.each do |c| %>
<%= image_tag c.avatar.url(:medium), :class=> "allBooksCover" %>
<% end %>
</div>
</div>
</div>
So when I click 'Computing' for example I get
undefined method `books' for nil:NilClass
and the params are being passed as
Parameters:{"id"=>"Computing"}
So, you need in your show action
#category = Category.where(:name => params[:id]).first
# etc

Resources