Accessing a method in rails controller via button/link - ruby-on-rails

I was trying to follow the solution on this thread - Rails 3 link or button that executes action in controller
I defined :update_question in my routes.rb file:
resources :surveys do
put :update_question, :on => :member
end
and in my controller:
class SurveysController < ApplicationController
before_action :set_survey, only: [:show, :edit, :update, :destroy]
before_action :set_question
# GET /surveys
# GET /surveys.json
def index
#surveys = Survey.all
end
# GET /surveys/1
# GET /surveys/1.json
def show
end
def survey
#survey = Survey.find(params[:survey_id])
end
# GET /surveys/new
def new
#survey = Survey.new
end
# GET /surveys/1/edit
def edit
end
def update_question
flash[:alert] = "getting there man"
end
And listed the link here in the html:
<%= link_to "Next Question", update_question_survey_path(#survey), {:method => :put} %>
However when I click the link I get this error:
Template is missing
Missing template surveys/update_question, application/update_question with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :raw, :ruby, :jbuilder, :coffee]}.
Which seems to elude that it's looking for a view - but really I just want it to run the method in my survey controller and update the question that's being displayed. Perhaps I'm going about this the wrong way, any help/suggestions is much appreciated!

That's because the action is correctly reached, but then Rails tries to render something. By default, it will look for a view file with the same name of the action.
You should do something like this:
def update_question
set_survey
# do stuff
flash[:alert] = "getting there man"
redirect_to survey_path(#survey)
end

Related

missing template rails problem with JSON rendering?

Has anyone come across this error before? I've looked online and couldn't find much information, perhaps I didn't render my JSON correctly?
Missing template answer/results, application/results with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :coffee, :jbuilder]}. Searched in: * "/Users/Minhaj/Desktop/my_survey/my_survey/app/views" * "/Users/Minhaj/.rvm/gems/ruby-2.4.1/gems/devise-4.5.0/app/views"
Here is the code. If there is an error, help will be appreciated in fixing it.
def create
#answer = current_survey.answers.create(question_id: question, choice_id: choice)
redirect_to question_survey_path(current_survey)
end
def results
#choices = choices_hash
#results = questions.map do |question|
{
question.question => CountChoicesService.call(question.id)
}
end
respond_to do |format|
format.html { render :nothing => true, :status => 204 }
format.json { render json: #results }
end
end
private
def question
#question ||= params[:question]
end
def choice
#choice ||= params[:choice]
end
def choices
#choices ||= Array.wrap(Choice.all)
end
def choices_hash
choices_hash = {}
choices.each { |choice| choices_hash[choice.id] = choice.choice }
choices_hash
end
def questions
#questions ||= Array.wrap(Question.all)
end
end
I appreciate the help in advance.
Here is how it should look like, controller name is plural
Under your controller directory, you should have this
# app/controller/answers_controller.rb
class AnswersController < ApplicationController
def results
end
end
Now in the views directory,the view namespace should be the same as the controller name.
# app/views/answers/results.html.erb
<h1>Check if this works</h1>
routes.rb
resources :answers do
collection/member do
get :results
end
end
Your problem is that you are not returning. Rails will render the associated template for the action unless you return. Try wrapping your render calls in return().
Side note, why are you using Array.wrap()? ActiveRecord’s all methods are array-like. They wait to execute the query until you actually try to iterate them, and then they act like an array. You shouldn’t need to make them an array. If you ever find that you do, you can call .to_a on them.
One thing to note about the active record record collection though, if you remove anything from its “array”, it will actually do a delete from the database, which may or may not be what you want.

link_to remote: true redirecting to HTML

At the /tags page I have a link with remote: true. It should be a link to an ajax request. But there are two requests, as JS and as HTML.
<%= link_to 'New', new_tag_path, class: "btn btn-outline btn-primary", remote: true %>
INFO -- : Started GET "/tags/new" for 192.168.18.236 at 2018-06-13 11:44:18 -0300
INFO -- : Processing by TagsController#new as JS
INFO -- : Rendered tags/_form.html.erb (41.0ms)
INFO -- : Rendered tags/_modal.html.erb (41.5ms)
INFO -- : Rendered tags/new.js.erb (49.2ms)
INFO -- : Completed 200 OK in 63ms (Views: 50.3ms | ActiveRecord: 2.2ms)
INFO -- : Started GET "/tags/new" for 192.168.18.236 at 2018-06-13 11:44:18 -0300
INFO -- : Processing by TagsController#new as HTML
INFO -- : Completed 500 Internal Server Error in 14ms (ActiveRecord: 1.9ms)
FATAL -- :
ActionView::MissingTemplate (Missing template tags/new, application/new with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]}. Searched in:
If I provide a new.html.erb, this MissingTemplate error is over, but the page is redirected to new.html.
What could be wrong with that request or that link?
Edit The controller code
class TagsController < ApplicationController
before_action :set_tag, only: [:show, :edit, :update, :destroy, :fix_correct_name]
before_action :set_tags, only: [:new, :edit]
# GET /tags/new
def new
#tag = Tag.new
end
# GET /tags/1/edit
def edit
end
# POST /tags
def create
#tag = Tag.new(tag_params)
respond_to do |format|
if #tag.save
format.html { redirect_to action: "index", notice: 'Tag adicionada.' }
else
format.html { render :new }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_tag
#tag = Tag.find(params[:id])
end
def set_tags
#tags = Tag.all.pluck(:name, :id)
end
# Never trust parameters from the scary internet, only allow the white list through.
def tag_params
params.fetch(:tag, {}).permit(:name, :parent_id, :tag_name, :parent_name, :no_parent)
end
end
In your new action, you’ll need a response_to to handle the ajax call
def new
#tag = Tag.new
respond_to { |format| format.js }
end
Also, you’ll need a new.js.erb file and a _new.html.erb partial to handle the response and update the view.
Inside your new.js.erb, you will have to render the view with something like this
$(“div-id-name”).html(“<%= j render partial: “new” %>”)
And your new partial will simply hold your form (or whatever is it you wanna render)
I made it work now, only replacing require jquery_ujs by require rails-ujs to application.js and adding rails-ujs gem.

Why am I getting a recordnotfound error when trying to access an instance in rails?

I have a user profile controller called "userinfo" and it's corresponding view. The userinfo index is the root path. In the homepage(which is the userinfo index), I have a link that takes you to the user profile page. It is giving me this error when I go to the home page:
My routes are:
My userinfos_controller:
class UserinfosController < ApplicationController
before_action :find_userinfo, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
def index
#userinfors = Userinfo.find(params[:id])
end
def show
#myvideo = Video.last
end
def new
#userinformation = current_user.userinfos.build
end
def create
#userinformation = current_user.userinfos.build(userinfo_params)
if #userinformation.save
redirect_to root_path
else
render 'new'
end
end
def edit
end
def update
end
def destroy
#userinformation.destroy
redirect_to userinfo_path
end
private
def userinfo_params
params.require(:userinfo).permit(:name, :email, :college, :gpa, :major)
end
def find_userinfo
#userinformation = Userinfo.find(params[:id])
end
end
and my view is:
<%= link_to 'profile', userinfors_path(#userinfors) %>
My routes.rb file:
Rails.application.routes.draw do
devise_for :users
resources :userinfos do
resources :videos
end
resources :pages
get '/application/decide' => 'application#decide'
root 'userinfos#index'
get '/userinfos/:id', to: 'userinfos#show', as: 'userinfors'
end
Thanks for any help!
ok, there are multiple errors and you are not following conventions of rails, index is not for what you have used.
Index is used to list all the users and show for a particular one with id passed in params.
Your index path is, as you can see, /userinfos which is correct and it doesn't have any id with it but you are trying to find user with params[:id] which is nil and hence the error.
Lets try out this:
def index
#userinfors = Userinfo.all #pagination is recommended
end
In your index view,
<% #userinfors.each do |userinfor| %>
<%= link_to "#{userinfor.name}'s profile", userinfo_path(userinfor) %>
<% end %>
It should work now.
Please read routing and action controller to get the idea and understand the magic behind rails routing and mvc architecture..

Controller method #show getting called

I have a link on my #index view:
<%= link_to 'Export Calendar (ICS)', { controller: :tickets, action: :ics_export, format: :ics }, class: "class-needed right" %>
routes.rb that pertains to this:
resources :tickets
get 'tickets/calendar' => 'tickets#ics_export'
post 'tickets' => 'tickets#index'
patch 'tickets/:id/close' => 'tickets#close', as: 'close_ticket'
post 'tickets/:id' => 'ticket_comments#create'
My TicketsController that pertains:
before_action :set_ticket, only: [:show, :edit, :destroy, :update, :close]
def show
#ticket_comment = TicketComment.new
end
def ics_export
tickets = Ticket.all
respond_to do |format|
format.html
format.ics do
cal = Icalendar::Calendar.new
tickets.each do |ticket|
event = Icalendar::Event.new
event.dtstart = ticket.start
event.description = ticket.summary
cal.add_event(event)
end
cal.publish
render :text => cal.to_ical
end
end
end
private
def set_ticket
#ticket = Ticket.find(params[:id])
end
And when I click the link, it takes me to /tickets/calendar.ics which is correct but I get the following error:
ActiveRecord::RecordNotFound in TicketsController#show
Couldn't find Ticket with 'id'=calendar
Extracted source (around line #83):
private
def set_ticket
#ticket = Ticket.find(params[:id])
end
The #ticket = Ticket.find(params[:id]) is highlighted. Which make sense that it is failing to call a ticket with an id of calendar.
Request has parameters:
{"id"=>"calendar",
"format"=>"ics"}
How do I fix this error? Why is it calling the show action?
There is a footnote in the canonical Rails Routing from the Outside In to the effect:
Rails routes are matched in the order they are specified, so if you have a resources :photos above a get 'photos/poll' the show action's route for the resources line will be matched before the get line. To fix this, move the get line above the resources line so that it is matched first.
As commented, the fix is to specify get 'tickets/calendar' => ... ahead of resources :tickets. If the order of routes is in question, you can run rake routes, which, to the best of my knowledge, should render your routes in the order they are checked.

Wicked gem not reaching step 1

I've been following step by step example for wicked gem https://github.com/schneems/wicked/wiki/Building-Partial-Objects-Step-by-Step but I'm struggling to make it work
routes.rb
post '/trips/building/build(.:format)', :to => "trips/build#create"
resources :trips do
resources :build, controller: 'trips/build'
end
trips_controller.rb
class TripsController < ApplicationController
include Wicked::Wizard
before_action :set_trip, only: [:show, :update]
steps :basic, :details
def show
render_wizard
end
def create
#trip = Trip.create
redirect_to wizard_path(steps.first, :trip_id => #trip.id
end
def update
#trip.update_attributes(trip_params)
render_wizard #trip
end
private
def set_trip
#trip = Trip.find(params[:trip_id])
end
def trip_params
....
end
end
index.html.erb
<%= link_to 'Create New Trip', '/trips/building/build', :method => :post, :class=>'btn btn-danger'%>
error in console:
Started POST "/trips/building/build" for 127.0.0.1 at 2014-04-16 22:50:20 -0700
ActionController::RoutingError - uninitialized constant Trips
this is driving me crazy...
any thoughts?
Your controller is named incorrectly - your route is pointing to the Trips::BuildController but your controller is defined as the TripsController.
The link you shared defines a Products::BuildController so that's why it works there.

Resources