Error 400 when commenting on ruby on rails ecommerce web app - ruby-on-rails

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])

Related

My Rails button is not updating the database

I created a button where users can input stuff in a field and then press the button to update the database (put request) which can be seen here in show.html.erb:
<% provide(:title, #user.name) %>
<div class="row">
<aside class="col-md-4">
<section class="user_info">
<h1>
<%= gravatar_for #user %>
<%= #user.name %>
<br>
<%= #user.email %>
<% if #errors %>
<p>THE FORM COULD NOT BE SAVED </p>
<ul id='errors'>
<% #errors.each do |error| %>
<li><%= error %></li>
<% end %>
</ul>
<% end %>
<br>
<% if is_admin? %>
<% if !#user.admin %>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#user) do |f| %>
<%= f.label :wistia_project_id %>
<%= f.text_field :wistia_project_id, class: 'form-control' %>
<%= f.submit "Save", :action => "set_wistia_project_ID", :method => :patch, :form_class => "form-control" %>
<% end %>
</div>
</div>
<% end %>
<% end %>
</h1>
</section>
</aside>
</div>
The function is in user_controller.rb:
# Sets wistia_project_ID.
def set_wistia_project_ID
#user = User.find(params[:id])
#user.set_project_id
unless #user.valid?
#errors = #user.errors.full_messages
render :show
end
end
That function calls another function, just to separate things more clearly. This other function lives in user.rb:
# Sets the wistia_project_ID.
def set_project_id!(val)
self.wistia_project_ID = val # self is necessary here
save # or self.save, but the self is unnecessary here
end
My routes.rb:
.
.
.
resources :users do
member do
patch 'set_wistia_project_ID'
end
end
My problem is that right now, when you press the button, it says: Completed 500 Internal Server Error in 26ms (ActiveRecord: 0.7ms)
and
NoMethodError (undefined method `set_project_id' for #<User:0x000055b1a0914ab8>
2019-06-26T14:46:34.940086+00:00 app[web.1]: Did you mean? wistia_project_id):
Zavitoski got it right. I suggest, however, that you're doing a number of things more fundamentally wrong. Given that you're early in your rails journey, I hope you don't mind if I point a few things out.
First, and to be nit-picky, yes, you created a button. But, it is not a button "where users can input stuff in a field and then press the button to update the database". You created a button on a form. And you created a field on that form. The user can input stuff into the field. And when clicked, the button submits the form which includes the information in the field.
Now, on that form, you did:
<%= form_for(#user) do |f| %>
<%= f.label :wistia_project_id %>
<%= f.text_field :wistia_project_id, class: 'form-control' %>
<%= f.submit "Save", :action => "set_wistia_project_ID", :method => :patch, :form_class => "form-control" %>
<% end %>
There are a few things wrong with:
:action => "set_wistia_project_ID"
First, set_wisteria_project_ID is not a very ruby-ish action name. set_wistia_project_id would be more like it. Also, you're using old-form key-value formatting. And, you can use a symbol instead of a string for your action name so your code is prettier. Something, perhaps, like:
<%= f.submit "Save", action: :set_wistia_project_id, method: :patch, form_class: "form-control" %>
But, that's a mistake, too. Because you don't need a set_wistia_project_id action. (It's an action or a method, not a function.) You already have the update action. And form_for is smart enough to submit to this action if #user is an instance of User. So, really, you should do:
<%= form_for #user do |f| %>
<%= f.label :wistia_project_id %>
<%= f.text_field :wistia_project_id, class: 'form-control' %>
<%= f.submit "Save", form_class: "form-control" %>
<% end %>
I'm not sure what form_class is, but I'll trust that it's correct.
Now, in your UsersController, just do:
class UsersController < ApplicationController
def update
#user = User.find(params[:id])
if user.update(user_params)
# do something successful
else
# do something unsuccessful
end
end
private
def user_params
# NOTE: You'll probably want to permit other stuff here, too.
params.require(:user).permit(:wistia_project_id)
end
end
Get rid of this:
class User < ApplicationRecord
# Sets the wistia_project_ID.
def set_project_id!(val)
self.wistia_project_ID = val # self is necessary here
save # or self.save, but the self is unnecessary here
end
end
Because you're just duplicating the update method. And, you probably want that attribute to be wistia_project_id, not wistia_project_ID. (Again, you never see _ID as the suffix in rails core and you might as well be conventional.) And, if you make sure you have your association set up correctly, ActiveRecord should make sure that wistia_project_id is actually a valid value.
And write your routes.rb like this:
resources :users
Because you don't need all that set_wistia_project_id business.
It appears that you are not calling the function by the name you defined, neither passing the parameter (project_id) needed.
def set_wistia_project_ID
#user = User.find(params[:id])
#user.set_project_id!(params[:wistia_project_id])
unless #user.valid?
#errors = #user.errors.full_messages
render :show
end
end
This should use the function you created and pass the parameter from the form.

param is missing or the value is empty: plant

I have added a custom action in my controller called transplant. I simply want to render a dropdown form to select where to be located based on the 'tray_id'
my routes look like this:
resources :plants do
member do
get 'transplant'
end
resources :plantdats, :plant_cycles, :tasks
end
My controller looks like this:
before_action :set_plant, only: [:show, :edit, :update, :destroy, :transplant]
def transplant
if #plant.update(plant_params)
redirect_to #plant
flash[:success] = "Transplanted successfully"
end
end
def set_plant
#plant = Plant.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def plant_params
params.require(:plant).permit(:title, :notes, :category_id, :tray_id, images_files: [])
end
Here is my button calling the action
<%= link_to 'TRANSPLANT', transplant_plant_path(#plant), class: "btn btn-raised btn-info hoverable" %>
Here is my transplant page _transplant.html.erb
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="jumbotron">
<%= form_for(#plant, html: {class: 'form-horizontal'}) do |f| %>
<% if #plant.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#plant.errors.count, "error") %> prohibited this grow from being saved:</h2>
<ul>
<% #plant.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.label 'NAME' %>
<%= f.hidden_field :tray_id, value: params[:tray_id] %>
<% if params[:tray_id].nil? %>
<%= f.collection_select(:tray_id, Tray.all, :id, :title) %></br></br>
<% end %>
<%= f.submit class: 'btn btn-raised hoverable btn-success' %>
<% end %>
</div>
</div>
</div>
EDIT
After implementing the route to post 'transplant
and changing my link code to
<%= link_to "TRANSPLANT", transplant_plant_path(#plant, tray_id: #plant.tray_id), method: "post", class: "btn btn-raised hoverable" %>
I still get the same error. It points right to the plant_params code in my controller.
These are the params that are being passed:
{"_method"=>"post",
"authenticity_token"=>"fhSKt2DpgTwt1J4HsoBqYFSs0B9+pgSvDDxrS/u6yo4c3gvSxYlrrFDmhbPXq+cMho/eTHY+194WZ8zpcb1txA==",
"id"=>"1",
"format"=>"1"}
Im simply trying to update the :tray_id
Ive been at this all day, can anyone help with the error that Im getting?
You should probably provide your code for your transplant action and view. Based on what you provided, it seems like you're trying to build a link, which changes the tray of a plant when clicked. If that's the case, transplant should probably be a POST route instead of GET. Also, you probably want to provide the tray_id in your post link like this:
<%= link_to "TRANSPLANT", transplant_plant_path(#plant, tray_id: {{your id}}), method: "post", class: "..." %>
Then you can get tray_id in your transplant through params[:tray_id] and re-associate your plant and tray
Essentially what I was trying to do was not easily done and my approach needed to change. I simply rendered the transplant form in my view and it works fine now. Thanks again :)
Check your routes you just have defined get route and your request is post after the form submission

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.

Rails 4: Unable to retrieve specific attributes of a model that `belongs_to` two other models?

So I have an Active model (think of it as a User) that uses Devise for authentication. I also have a Rushee model (you can think of them as products), and on each Rushee's profile page, I give Actives the option to leave a Rusheepost (think of them as product reviews).
I'll post some of my code first, then will describe the problem.
Here are my models:
class Rushee < ActiveRecord::Base
has_many :rusheeposts, dependent: :destroy
class Active < ActiveRecord::Base
has_many :rusheeposts, dependent: :destroy
class Rusheepost < ActiveRecord::Base
belongs_to :active
belongs_to :rushee
routes.rb
devise_for :actives, :path_prefix => 'my'
resources :actives, only: [:index, :show]
resources :rushees, only: [:index, :show] do
resources :rusheeposts, only: [:create, :destroy]
end
RusheepostsController
before_action :authenticate_active!
def create
#rushee = Rushee.find(params[:rushee_id])
#rusheepost = #rushee.rusheeposts.build(rusheepost_params)
#rusheepost.active = current_active
if #rusheepost.save
flash[:success] = "Comment created!"
redirect_to #rushee
else
flash[:error] = "There was an error with your comment; please try again."
redirect_to #rushee
end
end
private
def rusheepost_params
params.require(:rusheepost).permit(:content)
end
RusheesController (I only want signed in actives to be able to view rushees)
class RusheesController < ApplicationController
before_action :authenticate_active!
def show
#rushee = Rushee.find(params[:id])
#rusheeposts = #rushee.rusheeposts
#rusheepost = #rushee.rusheeposts.build if active_signed_in?
end
def index
#rushees = Rushee.all
end
end
show view for Rushees
<% provide(:title, #rushee.name) %>
<div class="row">
<aside class="span4">
<section>
<h1>
<%= #rushee.name %>
<%= #rushee.email %>
<%= #rushee.grade %>
<%= #rushee.major %>
</h1>
<section>
<%= render 'shared/rusheepost_form' %>
</section>
</section>
</aside>
<!-- Displays the rusheeposts that are associated with the current rushee -->
<div class="span8">
<% if #rushee.rusheeposts.any? %>
<h3>Comments (<%= #rusheeposts.count %>)</h3>
<ol class="rusheeposts">
<%= render #rusheeposts %>
</ol>
<% end %>
</div>
</div>
_rusheepost_form.html.erb
<%= form_for([#rushee, #rusheepost]) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose new comment..." %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
_rusheepost.html.erb
<li>
<span class="content"><%= rusheepost.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(rusheepost.created_at) %> ago by: <%= rusheepost.active.name %>
</span>
</li>
The Problem
The _rusheepost.html.erb partial does not render. The content renders correctly every time. However, if I put Posted <%= rusheepost.created_at %>, it renders to: Posted 2013-12-25 21:08:19 UTC. However, Posted <%= time_ago_in_words(rusheepost.created_at) %> gets me a undefined method '>' for nil:NilClass error.
Furthermore, just putting Posted by: <%= rusheepost.active.name %> gets me the same nilclass error. Putting Posted by: <%= rusheepost.active %>, however, gets me: Posted by: #<Active:0x007ff3466108a0>.
Strangely enough, everything works if I try to retrieve a rusheepost's rushee attribute. For instance, Posted by: <%= rusheepost.rushee %> yields Posted by: #<Rushee:0x007fa6681a56d8>. Similarly, Posted by: <%= rusheepost.rushee.name %> yields Posted by: Theodora Willms III, the name of the rushee who the post is associated with (and whose page I am on.) Obviously though, this isn't the functionality I want -- I want each post to display who posted it, not who the post is about.
Does anyone have any ideas as to why this might be happening? Maybe I didn't initialize something correctly? I am failing to see why I cannot retrieve attributes of a rusheepost's active, but I can retrieve attributes of a rusheepost's rushee. I also must note that before I added the form to create new rusheeposts, I had the resources in my routes.rb listed on top of each other (not nested), and everything rendered correctly, including this: Posted <%= time_ago_in_words(rusheepost.created_at) %> by: <%= rusheepost.active.name %>. After I nested the resources and changed my controllers to reflect the nesting, the problems I describe appeared.
Thanks, and sorry about the (very) long post. Let me know if there's any more information/code I can post that would help.
EDIT: I also must note that if I reset the database with no rusheeposts, then log in to my site, post on a rushee's page, and then go into rails console and type Rusheepost.first.active.name, I do in fact get the name of the Active that I was signed in as, which makes this all the more puzzling...
You've got => instead of %> terminating your Ruby code in your _rusheepost.html.erb file.
Solved. Needed to put #rusheeposts = #rushee.rusheeposts.all instead of #rusheeposts = #rushee.rusheeposts in my RusheesController, and this fixed the problem.

Submitting form info to Model from view, then invoking the model to run

I am trying to submit info from a form in my view, that passes the submitted info :hashtag into the model and then runs the model with that info. But it seems thats my model just runs with the words "hashtag" instead of the form info. I believe it is close. I just can't figure out where to go next.
home.html.erb
<div class="row">
<div class="span6 offset2">
<%= form_for :hashtag do |f| %>
<div class="input-prepend input-append">
<span class="add-on swag">#</span>
<%= f.text_field :hashtag , class: "span3 inverse", id:"appendedPrependedInput" %>
<%= f.submit "Swag!", class: "btn btn-inverse" %>
<% end %>
</div>
</div>
<div class="span4">
<div id="hashtags">
<% #random_hashtags.each do |hashtag| %>
<blockquote><%= hashtag.content %></blockquote>
<div class="from">— #<%= hashtag.screen_name %></div>
<% end %>
</div>
</div>
</div>
hashtag.rb
class Hashtag < ActiveRecord::Base
attr_accessible :content, :profile_image, :screen_name, :tweet_date, :tweet_id
def self.pull_hashtag
Twitter.search("%#{hashtag}").results.map do |tweet|
unless exists?(tweet_id: tweet.id)
create!(
tweet_id: tweet.id,
content: tweet.text,
profile_image: tweet.profile_image_url,
screen_name: tweet.from_user,
tweet_date: tweet.created_at
)
end
end
end
end
hashtags_controller
class HashtagsController < ApplicationController
def home
#random_hashtags = Hashtag.order("RANDOM()").limit(4)
end
def create
#hashtag = Hashtag.pull_hashtag(params[:search])
end
end
Updated code that I am currently using now as I was not posting anything to the model
It is going though on submit but it seems nothing from there.
Update 2,
I am trying to post the information to the database, by taking the info from the form, running a Twitter.search on it and creating the results in my database.
Can you try to replace with this?
form_for #hashtag, :url => :action => 'home'
my guess is that the action needs to be specified.

Resources