I have an app that helps a school to track students attendance to sports practices and games, I have all my index actions to render html, csv and xls formats and EVERYTHING GOES WELL. I have a special report that uses several model relations to complete, I am not required to render csv (I think this will be too complex to implement the to_csv method, I don't even have a clue where to put it, but this is not my problem), Now I created the equipos_controller#forma_rep method and a related view with a form to get the report's parameters, as you can see in the routes and controller code, it works fine when the report action renders the default HTML as you can see in the following log, parameters from the 'forma_rep.html.erb' form are in the params array..
Started POST "/equipos/reporte_asist" for 127.0.0.1 at 2017-01-05 18:37:51 -0600
Processing by EquiposController#reporte_asist as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"IP1O2bSgkGcSaUn5Sf9Tnp30yzxfP10+cA0h/1+XudoR7W8SoP6xveP3fwJpLFTvyRaBFdtqsqz5pCfYID5b5Q==", "entrenador"=>"1", "inicio"=>"2016-12-12", "final"=>"2016-12-20", "commit"=>"Crear Reporte"}
... most SQL ommited
Rendering equipos/reporte_asist.html.erb within layouts/application
Rendered equipos/reporte_asist.html.erb within layouts/application (69.4ms)
Rendered layouts/_shim.html.erb (0.5ms)
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
Rendered layouts/_header.html.erb (5.9ms)
Rendered layouts/_footer.html.erb (1.1ms)
Completed 200 OK in 210ms (Views: 165.2ms | ActiveRecord: 5.6ms)
But when I click the "Excel" link :
Started POST "/equipos/reporte_asist.xls" for 127.0.0.1 at 2017-01-05 18:37:56 -0600
Processing by EquiposController#reporte_asist as XLS
Parameters: {"authenticity_token"=>"oYVjNfxN5Qxt9FHC6PpeU0wQenD3p+otaxcGts1kZRuQlUL+6 BPE1pxqZznIKVkiGPIwWXPyBb/ivgCRss2HJA=="}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
Equipo Load (0.2ms) SELECT "equipos".* FROM "equipos" WHERE "equipos"."user_id" = ? [["user_id", 1]]
Completed 500 Internal Server Error in 11ms (ActiveRecord: 0.4ms)
NoMethodError (undefined method `<<' for nil:NilClass):
app/controllers/equipos_controller.rb:96:in `block in reporte_asist'
app/controllers/equipos_controller.rb:95:in `reporte_asist'
I can see that the parameters are not complete when I click the Excel link in the html file, how can I send them again? my routes work fine with the html version and the #index action renders fine in all formats, please help me.
Here is all code involved.
Routes:
resources :categorias
get '/equipos/forma_rep'
post '/equipos/reporte_asist', to: 'equipos#reporte_asist', as: 'reporte_asist'
resources :equipos
resources :players
app/controllers/equipos_controller.rb
def index
#equipos = Equipo.paginate(page: params[:page])
respond_to do |format|
format.html
format.csv { send_data #equipos.to_csv }
format.xls
end
end
# GET /equipos/forma_rep
def forma_rep
#equipo = Equipo.new
#entrenadores = User.all
end
# PUT /equipos/reporte_asist
def reporte_asist
if params[:entrenador]
#entrenador = User.find(params[:entrenador].to_i)
inicio = Time.parse(params[:inicio])
final = Time.parse(params[:final])
#equipos = #entrenador.equipos
#eventos = reporte(#entrenador.id, inicio, final)
else
#entrenador = current_user
#equipos = #entrenador.equipos
#equipos.each do |equi|
#eventos << equi.eventos
end
end
respond_to do |format|
format.html
format.xls
end
end
I have created the app/views/equipos/reporte_asist.xls.erb file with the XML directives as in..
<?xml version="1.0"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40">
<Worksheet ss:Name="Asistencias">
<Table>
<Row>
<Cell><Data ss:Type="String">Entrenador:</Data></Cell>
<Cell><Data ss:Type="String"><%= #entrenador.name %></Data> </Cell>
</Row>
....etc.
And this is the link I have in the app/views/equipos/reporte_asist.html.erb
<p>
Descargar:
<%= link_to "Excel", reporte_asist_path(format: "xls"), method: :post %>
</p>
Of course I have defined the Mime:Type.register in the config/initializers/mime_types.rb and requested the 'csv' library in my config/application.rb . I am using Rails 5.0.0.1 and Ruby 2.3.1 ...
This is the code that collects report parameter from user, it is inside the app/views/equipos/forma_rep.html.erb that posts to the reporte_asist.html.erb:
<h1>Reporte de Asistencias</h1>
<%= form_tag(reporte_asist_path) do %>
<%= label_tag(:entrenador, "Entrenador:") %>
<%= select_tag :entrenador, options_from_collection_for_select(#entrenadores, "id", "name"), prompt: "Seleccione el entrenador", class: 'form-control' %>
<%= label_tag(:inicio, "Fecha inicial de reporte:") %>
<%= date_field_tag :inicio, class: 'form-control' %>
<%= label_tag(:final, "Fecha final de reporte:") %>
<%= date_field_tag :final, class: 'form-control' %>
<%= submit_tag "Crear Reporte", class: "btn btn-default" %>
<% end %>
</div>
Initially this is the code that sends the report parameters, but once in the report view I cannot (and don't want to) re-render the form, that's why I put the link_to to the same controller but trying to render the excel
Add the parameters you want to POST to your reporte_asist_path helper, like this:
reporte_asist_path(format: 'xls', entrenador_id: #entrenador.id)
More information can be found here:
http://api.rubyonrails.org/classes/ActionDispatch/Routing/UrlFor.html#method-i-url_for
Also note that while using POST method for links is supported by Rails, it relies on JavaScript. If the user has JavaScript disabled, the request will fall back to GET method. So it's safer to use forms.
Related
First post, so i'm a newbie in StackOverflow. I'm trying for several days to make appear a Return button on a page form but only on a specific one.
So, I was advised to use backlink to make it appears.
Here's my code from the form where I want the return button
<% if #backlink.present? %>
<div class="spacer30"></div>
<% if #backlink == 'infos' %>
path = membre_path(menu: 'infos')
<% end %>
<% end %>
<%= link_to "Retour", path, class: "btn-rounded btn-turquoise btn-small" %>
Here's my code controller
def edit
super do |user|
puts "TEST PARAMS BACKLINK #{params[:backlink]}"
#backlink = params[:backlink]
end
end
and my route's :
get 'change_password', to: 'users/registrations#edit'
put 'update' => 'users/registrations#update', :as => 'user_registration'
get 'edit_password', to: 'users/registrations#edit', :as => 'user_edit'
So i should have in my log my PUTS 'TEST PARAMS BACKLINK' but nothing appear, only :
Started GET "/change_password.1?backlink=infos" for ::1 at 2017-10-04 10:07:41 +0200
Processing by Users::RegistrationsController#edit as
Parameters: {"backlink"=>"infos"}
User Load (9.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
Rendering users/registrations/edit.html.erb within layouts/application
Rendered users/registrations/edit.html.erb within layouts/application (14.4ms)
Rendered shared/_navbar.html.erb (4.0ms)
Rendered shared/_flashes.html.erb (1.1ms)
Completed 200 OK in 231ms (Views: 217.0ms | ActiveRecord: 9.1ms)
Any ideas why it doesn't work?
Many thanks.
I just had to delete some lines, here's what i changed from my registration controller :
def edit
#backlink = params[:backlink]
super
end
This way, it appears exactly the way I wanted to.
Many thanks :)
I'm following Michael Hartl tutorial about Rails 5 ActionCable, to build a simple chat, and a problem is occurring inside my create action in MessageController:
def create
message = current_user.messages.build(message_params)
if message.save
ActionCable.server.broadcast 'room_channel',
content: message.content,
username: message.user.username
head :ok
end
end
It goes until head :ok, and after that, display an empty HTML page. The log is:
Processing by MessagesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"h9UsB78aX8mO8Nyn8eZEUuDzAOxL4V7UCMwNuTfwALliMv7OCkcUIeR4/xXIcvPjwq9H1bphjn6G96G+0VYisw==", "message"=>{"content"=>"oi"}, "commit"=>"Send"}
User Load (1.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
Message Load (2.1ms) SELECT "messages".* FROM "messages" ORDER BY "messages"."created_at" DESC LIMIT ? [["LIMIT", 50]]
(0.3ms) begin transaction
SQL (9.3ms) INSERT INTO "messages" ("content", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["content", "oi"], ["user_id", 1], ["created_at", 2016-09-19 02:12:58 UTC], ["updated_at", 2016-09-19 02:12:58 UTC]]
(9.1ms) commit transaction
[ActionCable] Broadcasting to room_channel: {:content=>"oi", :username=>"alice"}
Completed 200 OK in 69ms (ActiveRecord: 22.0ms)
RoomChannel transmitting {"content"=>"oi", "username"=>"alice"} (via streamed from room_channel)
Finished "/cable/" [WebSocket] for 10.0.2.2 at 2016-09-19 02:12:58 +0000
RoomChannel stopped streaming from room_channel
(After that, I can refresh the page and the message is displayed properly)
Why that is happening?
My RoomChanel class:
class RoomChannel < ApplicationCable::Channel
def subscribed
stream_from "room_channel"
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
end
end
My room.coffee
App.room = App.cable.subscriptions.create "RoomChannel",
connected: ->
# Called when the subscription is ready for use on the server
disconnected: ->
# Called when the subscription has been terminated by the server
received: (data) ->
alert data.content
I know the answer is accepted already, but this solution worked for me without having to remove head :ok, maybe it helps somebody out.
Normally in the development environment people are running localhost:3000 but i was running on a different port, localhost:3030.
And this case i had to add an allowed request origin for that port, like so:
config.action_cable.allowed_request_origins = [
'http://localhost:3030'
]
to my /config/environments/development.rb
Following a sugestion, I'm adding as answer what I did to get around this problem. It doesn't answer why that happens, but solve the problem.
The solution is: remove head :ok.
Aparently it's unecessary, because if I add a test whit assert_response :success to the action, it'll pass.
I'm following Michael's tutorial for ActionCable and had the same problem.
I think this was due to the format of the form partial _anything.html.erb.
app/views/messages/_message_form.html
As you go through the tutorial, you're upgrading to Action Cable features. But in the _message_form partial, it is still with the usual HTTP request. So after you broadcast a message using the messages_controller.rb, the browser render an empty page because the form was already rendered.
app/views/messages/_message_form.html, Originally:
<div class="message-input">
<%= form_for(#message) do |f| %>
<%= f.text_area :content %>
<%= f.submit "Send" %>
<% end %>
</div>
So, you have to add the remote: true to the form, like this:
<div class="message-input">
<%= form_for(#message, remote: true) do |f| %>
<%= f.text_area :content %>
<%= f.submit "Send" %>
<% end %>
</div>
Adding the remote: true makes an JS request (Ajax, in this case)
Quoting Michael:
You can verify by submitting a message that it appears as desired, but in
fact this is a cheat because the form from Listing 6 is currently submitting
an ordinary HTTP POST request, which causes the page to refresh. In order
to use Action Cable, we need to change the form to submit a remote request
that submits an Ajax request without refreshing the page. We can do this by
including the remote: true option in the call to form_for.
Note that I'm doing everything in localhost:3000
So far, to a very experienced Java EE developer with years of experience in many different languages, I am having real difficulties with Ruby on Rails. I am using: ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15] and Rails 5.0.0. I am following a very simple on-line tutorial on building a private library web application, BUT, in order to learn something, instead of having Books with a linked table of Subjects, I changed Subjects to Authors since many books have the same authors. I am using SQLLite for development and MySQL for production( haven't gotten there yet! ). I find that when you follow exactly the directions in most tutorials, you end up with whatever application you were building. But, IF you deviate in any fashion, things just don't work and it's very hard to figure out what happened. You get error messages ( sometimes ) in the logs that you've got an undefined variable or constant. Normally, you would search for where that variable is used, then be sure you define it or spell it correctly. However, in RoR, that constant doesn't appear anywhere except in the log, if there. RoR, due to its conventions, has either created or assumed that you had such a variable, when in fact, you may have named a "view" folder in the singular instead of the plural. It "invented" a variable to point to that, but it didn't match the pattern, so it fails with very poor error messages.
The server doesn't complain, just does a rollback, and goes on. The log has some unmeaningful message, as per above. I end up spending hours trying different patterns for routes suggested by people, or renaming things, but it's all guesswork.
I enjoy working with frameworks and systems where I understand them. This seems to be a collection of different pieces which parse in yml, yaml, erb, rb, sass, haml, etc. I've tried logging, but to no avail. How do you located simple mistakes?
Here is my "books_controller.rb":
class BooksController < ApplicationController
def list
#books = Book.all
end
def show
#book = Book.find(params[:id])
end
def new
#book = Book.new
#authors = Author.all
end
def create
#book = Book.new(book_params)
if #book.save
logger.debug 'Redirecting to list'
redirect_to :action => 'list'
else
#authors = Author.all
render :action => 'new'
end
end
def edit
#book = Book.find(params[:id])
#authors = Author.all
end
def update
#book = Book.find(params[:id])
if #book.update_attributes(book_params)
redirect_to :action => 'show', :id => #book
else
#authors = Author.all
render :action => 'edit'
end
end
def delete
Book.find(params[:id]).destroy
redirect_to :action => 'list'
end
def show_authors
#author = Author.find(params[:id])
end
def book_params
params.require(:books).permit(:title, :description, :author_id)
end
end
The new.html.erb under app/views/books is:
<h1>Add new book</h1>
<%= form_tag :action => 'create' do %>
<p><label for = "book_title">Title</label>:
<%= text_field 'books', 'title' %></p>
<p><label for = "book_author_id">Author</label>:
<%= collection_select(:book, :author_id, #authors, :id, :name, prompt: true) %></p>
<p><label for = "book_description">Description</label><br/>
<%= text_area 'books', 'description' %></p>
<%= submit_tag "Create" %>
<% end -%>
<%= link_to 'Back', {:action => 'list'} %>
routes.rb is:
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
resources :books
#get 'books/list'
#post 'books/create'
#get 'books/new'
#patch 'books/update'
#get 'books/show'
#get 'books/edit'
#get 'books/delete'
get 'books/show_authors'
get 'authors/list'
post 'authors/create'
get 'authors/new'
patch 'authors/update'
get 'authors/show'
get 'authors/edit'
root :to => 'books#list'
end
When I try to add a new book, I enter the title, select an author, and put in a description and click "Create". It then just returns to the new screen. The console has:
Started GET "/books/new" for ::1 at 2016-08-04 17:18:22 -0400
Processing by BooksController#new as HTML
Rendering books/new.html.erb within layouts/application
Author Load (0.1ms) SELECT "authors".* FROM "authors"
Rendered books/new.html.erb within layouts/application (5.4ms)
Completed 200 OK in 26ms (Views: 21.6ms | ActiveRecord: 0.5ms)
Started POST "/books" for ::1 at 2016-08-04 17:18:28 -0400
Processing by BooksController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"noRmEq8rHE6RLs0cPNrlZoQXq//2sr+SAOSHEFc0U3zqbSJZOSKDmdgwpdm5/nVswItHp4Ken0mjggt47ph46Q==", "books"=>{"title"=>"sdfasdf", "description"=>"asdfasdf"}, "book"=>{"author_id"=>"2"}, "commit"=>"Create"}
(0.1ms) begin transaction
(0.1ms) rollback transaction
Rendering books/new.html.erb within layouts/application
Author Load (0.1ms) SELECT "authors".* FROM "authors"
Rendered books/new.html.erb within layouts/application (2.0ms)
Completed 200 OK in 24ms (Views: 20.3ms | ActiveRecord: 0.2ms)
and the development log has:
Started GET "/books/new" for ::1 at 2016-08-04 17:18:22 -0400
Processing by BooksController#new as HTML
Rendering books/new.html.erb within layouts/application
[1m[36mAuthor Load (0.1ms)[0m [1m[34mSELECT "authors".* FROM "authors"[0m
Rendered books/new.html.erb within layouts/application (5.4ms)
Completed 200 OK in 26ms (Views: 21.6ms | ActiveRecord: 0.5ms)
Started POST "/books" for ::1 at 2016-08-04 17:18:28 -0400
Processing by BooksController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"noRmEq8rHE6RLs0cPNrlZoQXq//2sr+SAOSHEFc0U3zqbSJZOSKDmdgwpdm5/nVswItHp4Ken0mjggt47ph46Q==", "books"=>{"title"=>"sdfasdf", "description"=>"asdfasdf"}, "book"=>{"author_id"=>"2"}, "commit"=>"Create"}
[1m[35m (0.1ms)[0m [1m[36mbegin transaction[0m
[1m[35m (0.1ms)[0m [1m[31mrollback transaction[0m
Rendering books/new.html.erb within layouts/application
[1m[36mAuthor Load (0.1ms)[0m [1m[34mSELECT "authors".* FROM "authors"[0m
Rendered books/new.html.erb within layouts/application (2.0ms)
Completed 200 OK in 24ms (Views: 20.3ms | ActiveRecord: 0.2ms)
Yes, the transaction was rolled back. WHY? How can I get information on what caused the database to "rollback"? The two tables in the database are:
class CreateBooks < ActiveRecord::Migration[5.0]
def change
create_table :books do |t|
t.string :title
t.integer :author_id
t.string :description
t.timestamp :created
t.timestamps
end
end
end
class CreateAuthors < ActiveRecord::Migration[5.0]
def change
create_table :authors do |t|
t.string :name
t.timestamps
end
end
end
class Book < ApplicationRecord
belongs_to :author
validates_presence_of :title
end
class Author < ApplicationRecord
has_many :books
end
I can create a book in rails console as:
b=Book.create :title=>'Test', :author_id=>1, :description=>'Desc'
(0.1ms) begin transaction
Author Load (0.1ms) SELECT "authors".* FROM "authors" WHERE "authors"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
SQL (0.3ms) INSERT INTO "books" ("title", "author_id", "description", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) [["title", "Test"], ["author_id", 1], ["description", "Desc"], ["created_at", 2016-08-04 20:17:40 UTC], ["updated_at", 2016-08-04 20:17:40 UTC]]
(2.4ms) commit transaction
=> #<Book id: 1, title: "Test", author_id: 1, description: "Desc", created: nil, created_at: "2016-08-04 20:17:40", updated_at: "2016-08-04 20:17:40">
I would appreciate input and especially help on understanding why what happened actually happened. It seems that a very simple error is being made, but I can't see it.
------------------ Added after several answers and "guesses" by me.
I changed the form_tag to a form_for as I'll show below.
----new.html.erb------
<%= form_for(#book) do |f| %>
Title: <%= f.text_field :title %><br/>
Author: <%= select("book", "author_id", Author.all.collect{|p| [p.name,p.id]}, prompt: 'Select') %><br/>
Description: <%= f.text_area :description %><br/>
<%= f.submit "Create" %>
<% end -%>
<%= link_to 'Back', {:action => 'list'} %>
I get in the browser:
Validation failed: Author must exist, Title can't be blank
Extracted source (around line #18):
16
17
18
19
20
21
def create
#book = Book.new
if #book.save!
redirect_to :action => 'list'
else
#authors = Author.all
Rails.root: /Users/woo/Development/rails/library
Application Trace | Framework Trace | Full Trace
app/controllers/books_controller.rb:18:in `create'
Request
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"gi+wVGV3MIlkJsRjO8Ig1cS3YV/OIADSevFJg7ItBesokIiHFDThycTO8/kob+2E1fuPFquFUK+b7bGksWRZGQ==",
"book"=>{"title"=>"Book", "author_id"=>"2", "description"=>"test"},
"commit"=>"Create"}
As far as I can see, book does have a title, and an author_id, and a description. Why "Author must exist, Title can't be blank"?
Try using form_for instead of form_tag in your books/new view. This is the Rails way to create forms for model object.
Check a handy guide on form_for here.
How to debug ....
There are several tools to help debug a Rails application. One you have already discovered: the log file in log/development.log.
Another is Byebug. Add the gem to your Gemfile and insert the following in the create action after the 'else':
require 'byebug'
byebug
then post the form again. The development server will bring up a Byebug console where you can inspect local variables, instance variables, and the stack trace. Try inspecting:
#book.errors
When an ActiveRecord model fails to save it is usually because validations failed. Errors encountered when saving are added to the errors object on the model instance.
The reason for the failure is probably that the form is not passing the expected parameters. By convention, Rails expects attributes for the model to be in a hash where the key is the model name, so params[:book][:title], not params[:title]. See the documentation for the form_for helper for more info.
Thanks for the help. With your suggestions and a lot of guessing from ready various Google sites, I combined them and in the new.html.erb put form_for(#book), and then in the create method of books_controller.rb, I put #book - Book.new(book_params), where book_params is:
def book_params
params.require(:book).permit(:title, :author_id, :description)
end
I'm guessing that this is to handle the strong attribution required by Rails 4 and up. Before I had books as the first argument and since it existed, but book was not filled, I got the weird error. After using form_for with #book as an argument, that set the values from the form into the book hash. Then the params.require with :book as the first argument, looked in that hash to extract title, author_id, and description.
Again, many thanks for the help and I learned about bye bug and save! and so forth. I find information is very sketchy and ofter the version is not mentioned, thus leading one astray many times.
Hey guys not sure what's going on here. I have Movies and Critics on my app. I've set up an assocation between those and Reviews. I'm trying to set up the controller and form to create and destroy Reviews. In the rails console I can create reviews that belong to both just fine and I have tested my controller (may be incorrect though) and it seems to be working, so I think the problem is in my form. Thanks in advance guys. Here's the codeand server logs:
class ReviewsController < ApplicationController
def create
#movie = Movie.find(params[:movie_id])
current_critic.reviews.create(content: params[:content], movie_id: #movie.id)
redirect_to #movie
end
def destroy
#movie = Movie.find(params[:movie_id])
#review = current_critic.reviews.find_by(movie_id: #movie.id)
#review.delete
redirect_to #movie
end
end
form:
<div class="form">
<h1 class="smaller">Write a Review</h1>
<%= form_for(current_critic.reviews.new) do |r| %>
<%= hidden_field_tag :movie_id, #movie.id %>
<ul>
<li>
<%= r.text_area :content, placeholder: "Write your review...", size: "50x10" %>
</li>
<li>
<%= r.submit "Submit Review" %>
</li>
</ul>
<% end %>
</div>
server log after submitting form:
Started POST "/reviews" for 99.39.164.184 at 2015-12-04 20:34:59 +0000
Processing by ReviewsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"d16BVZxzqZY5bQrw9xr2VlWbWjh0Dc7bL6t4OgKQPk1RXWt40acMjtkjXG9DUBBfnA7K06iJDwQzd5YJ0D6c4Q==", "movie_id"=>"2", "review"=>{"content"=>"One last try at writing and submitting a review before I head out"}, "commit"=>"Submit Review"}
Movie Load (2.1ms) SELECT "movies".* FROM "movies" WHERE "movies"."id" = ? LIMIT 1 [["id", 2]]
Critic Load (0.2ms) SELECT "critics".* FROM "critics" WHERE "critics"."id" = ? LIMIT 1 [["id", 1]]
(5.3ms) begin transaction
(0.9ms) commit transaction
Redirected to https://everyones-a-critic-caedbudris.c9users.io/movies/2
Completed 302 Found in 574ms (ActiveRecord: 18.1ms)
EDIT: I implemented strong paramaters for create so the controller is now
def create
#movie = Movie.find(params[:movie_id])
current_critic.reviews.create(review_params)
redirect_to #movie
end
private
def review_params
params.require(:review).permit(:content, :movie_id)
end
And it is now inserting into reviews, but for some reason it's not getting the movie_id passed by the hidden_field_tag. Why is this?
Started POST "/reviews" for 99.39.164.184 at 2015-12-05 21:31:07 +0000
Processing by ReviewsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"OlBIfneoWTvBtIeISTF9ubo9jj06oVyfDd6rswxe7xO+JyGXRvFV4TLD+3xKhBZHRF+eRJAawKUabU7KrLpZow==", "movie_id"=>"2", "review"=>{"content"=>"review review review review review"}, "commit"=>"Submit Review"}
Movie Load (0.3ms) SELECT "movies".* FROM "movies" WHERE "movies"."id" = ? LIMIT 1 [["id", 2]]
Critic Load (0.3ms) SELECT "critics".* FROM "critics" WHERE "critics"."id" = ? LIMIT 1 [["id", 1]]
(0.1ms) begin transaction
SQL (6.4ms) INSERT INTO "reviews" ("content", "critic_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["content", "review review review review review"], ["critic_id", 1], ["created_at", "2015-12-05 21:31:08.185722"], ["updated_at", "2015-12-05 21:31:08.185722"]]
(10.3ms) commit transaction
Redirected to https://everyones-a-critic-caedbudris.c9users.io/movies/2
Completed 302 Found in 157ms (ActiveRecord: 25.6ms)
You should whitelist your parameters, by default rails won't accept any parameters to avoid mass assignment. Proper way is to define a protected block at the bottom of your controller. Like this,
protected
def rating_params
params.require(:rating).permit(:content)
end
And you can use it like
current_critic.reviews.create(rating_params)
I'm having some issue with my form_tag search functionality is not redirecting me properly to a place where I can see the results of my search.
It was working fine yesterday, Once the submit button of the search is clicked, a get request to the pets controller search method is fired and then I was redirected to the results.html.erb page where the results are displayed.
The problem is that now when I submit the search, it's just refreshing the page (index.html.erb) and my params are passed to the URL but none of the "pets" i searched for are displayed.
http://localhost:3000/?utf8=%E2%9C%93&authenticity_token=iDXugIhTyjknCMpPh2P5x7voNMSQ3Y7Aa1HIZPA7xqZ9Oj4CAuVc5eJPqfE1CLwxXAsCebgPuNWqpOk381TlvQ%3D%3D&pets%5Bzip_code%5D=10019&pets%5Bspecies%5D=Cat&pets%5Bbreed%5D=&pets%5Bage%5D=&pets%5Bsex%5D=&pets%5Bsize%5D=&commit=Find+Pets%21
Before it was just redirecting me the results page localhost:3000/results
Here is my pets controller
class PetsController < ApplicationController
def index #index page will render search form
#pet = Pet.new
#send form data in params to create
end
def search
#pets = Pet.where(clean_params)
render :results
end
private
def thinned_params
params["pets"].delete_if {|k, v| v.empty?}
end
def clean_params
thinned_params.permit(:species, :zip_code, :sex, :size, :breed, :age)
end
end
My form_tag in welcome#index:
<form class="form-horizontal">
<%= form_tag :controller => 'pets', :action => 'search', :method => 'get' do %>
<%= label_tag('pets[zip_code]', "Zipcode") %>
<%= text_field_tag('pets[zip_code]') %>
<%= label_tag('pets[species]', "Type") %>
<%= select_tag('pets[species]', options_for_select([["Dog","Dog"],["Cat","Cat"],["Rabbit", "Rabbit"], ["Small & Furry","Smallfurry"],["Horse", "Horse"],["Pig", "Pig"],["Reptile", "Reptile"],["Bird", "Bird"],["Barnyard", "Barnyard"]])) %>
<%= label_tag('pets[breed]', "Breed") %>
<%= text_field_tag('pets[breed]', nil, class: 'typeahead') %>
<%= label_tag('pets[age]', "Age") %>
<%= select_tag('pets[age]', options_for_select([["None",""],["Baby","Baby"],["Young","Young"],["Adult", "Adult"], ["Senior","Senior"]])) %>
<%= label_tag('pets[sex]', "Gender") %>
<%= select_tag('pets[sex]', options_for_select([["None",""],["Male","M"],["Female","F"]])) %>
<%= label_tag('pets[size]', "Size") %>
<%= select_tag('pets[size]', options_for_select([["None",""],["Small","S"],["Medium","M"], ["Large", "L"], ["Xtra Large", "XL"]])) %>
<%= submit_tag "Find Pets!" %>
<%end%>
</form>
And finally...my routes.rb
Rails.application.routes.draw do
devise_for :users
resources :users
# resources :pets
root 'welcome#index'
get '/pets' => 'pets#index'
post '/pets/search' => 'pets#search'
resources :favorite_pets
get '/my_pets' => 'users#my_pets'
end
So my question is why is my params passed to the URL when it should just hit the search method in the pets controller and redirect me to the results page displaying the info?
Second question, obviously, what can I do to fix this problem?
UPDATE
here is the output of my console when the "search" button is clicked.
Started GET "/?utf8=%E2%9C%93&authenticity_token=NgVe%2Fe5i6sn8ijRmgcvOezp62KlymrNRWPJfFNOVJ54ChWpZf8JYTm%2Fk%2FeHdDsvcgzdBYe%2BjUX5jiz2JeALEpQ%3D%3D&pets%5Bzip_code%5D=10019&pets%5Bspecies%5D=Cat&pets%5Bbreed%5D=&pets%5Bage%5D=&pets%5Bsex%5D=&pets%5Bsize%5D=&commit=Find+Pets%21" for ::1 at 2015-03-15 15:54:34 -0400
Processing by WelcomeController#index as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"NgVe/e5i6sn8ijRmgcvOezp62KlymrNRWPJfFNOVJ54ChWpZf8JYTm/k/eHdDsvcgzdBYe+jUX5jiz2JeALEpQ==", "pets"=>{"zip_code"=>"10019", "species"=>"Cat", "breed"=>"", "age"=>"", "sex"=>"", "size"=>""}, "commit"=>"Find Pets!"}
Pet Load (0.7ms) SELECT "pets".* FROM "pets"
CACHE (0.0ms) SELECT "pets".* FROM "pets"
CACHE (0.0ms) SELECT "pets".* FROM "pets"
CACHE (0.0ms) SELECT "pets".* FROM "pets"
Breed Load (0.2ms) SELECT "breeds".* FROM "breeds" INNER JOIN "pet_breeds" ON "breeds"."id" = "pet_breeds"."breed_id" WHERE "pet_breeds"."pet_id" = ? [["pet_id", 71]]
Shelter Load (0.1ms) SELECT "shelters".* FROM "shelters" WHERE "shelters"."id" = ? LIMIT 1 [["id", 26]]
Breed Load (0.3ms) SELECT "breeds".* FROM "breeds" INNER JOIN "pet_breeds" ON "breeds"."id" = "pet_breeds"."breed_id" WHERE "pet_breeds"."pet_id" = ? [["pet_id", 73]]
CACHE (0.0ms) SELECT "shelters".* FROM "shelters" WHERE "shelters"."id" = ? LIMIT 1 [["id", "26"]]
Breed Load (0.1ms) SELECT "breeds".* FROM "breeds" INNER JOIN "pet_breeds" ON "breeds"."id" = "pet_breeds"."breed_id" WHERE "pet_breeds"."pet_id" = ? [["pet_id", 41]]
Shelter Load (0.1ms) SELECT "shelters".* FROM "shelters" WHERE "shelters"."id" = ? LIMIT 1 [["id", 16]]
Breed Load (0.1ms) SELECT "breeds".* FROM "breeds" INNER JOIN "pet_breeds" ON "breeds"."id" = "pet_breeds"."breed_id" WHERE "pet_breeds"."pet_id" = ? [["pet_id", 9]]
Shelter Load (0.1ms) SELECT "shelters".* FROM "shelters" WHERE "shelters"."id" = ? LIMIT 1 [["id", 5]]
Rendered welcome/index.html.erb within layouts/application (20.9ms)
Completed 200 OK in 127ms (Views: 125.2ms | ActiveRecord: 1.6ms)
Rake Routes
https://slack-files.com/files-pub/T02MD9XTF-F041PKBE2-532b801cb1/-.txt
According to your routes file, the search action only accepts POST (not GET):
post '/pets/search' => 'pets#search'
That seems appropriate, so just change your form action to use the POST method:
form_tag :controller => 'pets', :action => 'search', :method => :post
Your route is POST, but that makes no sense, are you trying to update or replace pets? No, you getting a list of pets. You are already calling a GET request in your form, so you can leave that, and change
post '/pets/search' => 'pets#search' to get '/pets/search' => 'pets#search'
More information on get and post.