I am new in ruby on rails and i am trying to pass id in url from one controller to another controller. And i am getting this error.
Couldn't find Tournament without an ID
And here is my code:
matches View
<h2 class="text-center mt-4"><%= #tournaments.id %></h2>
<h2 class="text-center mt-4"><%= #tournaments.title %></h2>
<p>
<% #players = #tournaments.player_ids %>
Players = <%= #players.uniq %>
</p>
<div class="container">
<div class="row justify-content-md-center">
<div class="col-8 mt-4">
<div class="card text-center shadow mb-5 bg-white rounded">
<div class="card-header font-italic">
</div>
<div class="card-body">
<%= link_to "Edit", edit_tournament_path(#tournaments), class: "btn btn-outline-info" %>
<%= link_to "Delete", tournament_path(#tournaments), method: "delete", class: "btn btn-outline-danger", data: {confirm: "Are you sure you want to delete?"} %>
</div>
</div>
</div>
<p><%= link_to "All Tournaments", root_path, class: "btn btn-outline-primary float-right" %></p>
<p><%= link_to "Schedules", matches_path(#touraments), class: "btn btn-outline-primary float-right" %></p>
</div>
This is my another controller where i want this data:
class MatchesController < ApplicationController
def index
#match = Tournament.find(params[:id])
end
end
I'll advise you to check your params before assignation. I'm almost sure that you'll find something like
#<ActionController::Parameters {"controller"=>"matches", "action"=>"index", "tournament_id"=>"666"} permitted: false>
Which means you simple need to adjust your controller with:
class MatchesController < ApplicationController
def index
#match = Tournament.find(params[:tournament_id])
end
end
An index route does not accept an id by default, so actually Rails will be interpreting the tournament id as a format and creating a URI like /matches.13 based on your code.
Instead you need to actually pass it as a parameter like this: matches_path(tournament_id: #tournaments) and then in your controller it will be available as params[:tournament_id]
Related
I created a form on my application that is suposed to delete some media on my app.
I have a Album entity that has some media on it. I created a partial called media_uploader so I can reuse it on other places. Im calling my partial from the albums/new view. Like this:
<%= render '/profiles/edit/sidebar', user: current_user %>
<article class="col-9 col-offset-1">
<h3 class="color-gray-medium">Album Info</h3>
<div class="row row-no-padding top-5">
<%= form_for #album do |f| %>
<div class="col-9">
<div class="form-group row" >
<div class="col-6">
<label for="">Name:</label>
<%= f.text_field :name %>
</div>
</div>
</div>
<div class="col-9">
<div class="form-group row" >
<div class="col-6">
<%= render 'shared/media_uploader', media_contents: #media_contents %>
</div>
</div>
</div>
shared/_media_uploader.html.erb
<%= link_to 'Delete', delete_media_path, method: :delete, id: 'delete-all', class: 'btn btn-danger', disabled: media_contents.empty? %>
<br><br>
<div class="row">
<div id="media-contents" class="col-12">
<% if media_contents.empty? %>
<h5 id="no-media">No Media Found</h5>
<% else %>
<% media_contents.each do |media| %>
<div class="col-4">
<div class="thumbnail">
<%= image_tag media.file_name_url(:thumb) %>
<div class="caption">
<p>
<%= check_box_tag 'media_contents[]', media.id %>
</p>
</div>
</div>
</div>
<% end %>
</div>
</div>
<% end %>
<% end %>
My routes are like this:
resources :media_contents, only: [:create]
delete 'delete_media', to: "media_contents#delete_media"
delete 'delete_all', to: 'media_contents#delete_all'
When I click on the delete button here:
<%= form_tag({controller: "media_contents", action: "delete_media"}, method: "delete") do %>
<%= submit_tag 'Delete', id: 'delete', class: 'btn btn-danger', disabled: media_contents.empty? %>
It gives a error:
No route matches [DELETE] "/albums"
I understand that this is caused because of the outside form_for: #album.
The question is: "How can I do this?" How can I, inside this #album form, call a method from another controller and make it works?
Looks like you routes of media_contents is limited to "create"
Adding :delete could solve the issue
resources :media_contents, only: [:create, :delete]
Also why add a custom routes for delete when DELETE action already exists for the controller?
I could be that your form_tag of media_contents is inside the form_tag of albums.
That could be one of the reasons it's calling "albums" controller
You can't use form inside another form, it is invalid html. But you can use 2 submit buttons and decide what to do inside the controller action, depending on commit parameter. You need to remove inner form_tag from the partial and change update action like:
if params[:commit] == "Delete"
# deletion logic or redirect to needed delete action goes here
else
# existing `update` goes here
end
On my lists show page, I display the movies that belong to that list. I have a button that, when pressed, should sort the movies in that list by title. I think I'm on the right track, but I can't seem the get the view to update after the button is clicked.
Here is my list.rb model where I've defined an order_list method:
def order_list(sort_by)
if sort_by == 'title' || sort_by.blank?
self.movies.order(title: :asc)
elsif sort_by == 'rating'
self.movies.order(rating: :asc)
else
self.movies.order(created_at: :asc)
end
end
And here is my controller action for lists#show:
def show
#list.movies.order_list(params[:sort_by])
end
I've also made sure to include the :sort_by in my permitted params.
And finally, here's my link_to button on the show.html.erb for my lists:
<%= link_to "Sort By Title", list_path(sort_by: 'title'), class: 'btn btn-secondary btn-sm btn-space' %>
My show.html.erb:
<div class="container-fluid text-center">
<h2><strong><%= #list.name %></strong></h2>
</div>
<div class="text-center">
<h2><strong><% #list.average_rating.to_i.ceil.times do %></strong></h2>
<span><%= fa_icon "star" %></span>
<% end %>
</div>
<div class="container-fluid text-center">
<span>
<%= link_to "Sort By Title", list_path(#list.id, sort_by: 'title'), class: 'btn btn-secondary btn-sm btn-space' %>
<button class="btn btn-sm btn-space btn-secondary" id="sort-ratings">Sort By Rating</button>
</span>
</div>
<div class="card-deck text-center" id="card-deck">
<% #list.movies.each do |m| %>
<div class="card">
<img src="<%= m.poster %>" alt="No poster found." class="card-img-top">
<div class="card-body">
<h5 class="card-title"><%= m.title %></h5>
<p class="card-text"><%= m.genre %></p>
<p class="card-text">Director: <%= m.director %></p>
<p class="card-text"><%= m.plot %></p>
</div>
<div class="card-footer">
Rating: <% m.rating.times do %>
<span><%= fa_icon "star" %></span>
<% end %>
<div class="btn-top">
<span class="btn-group">
<%= button_to "Edit movie", edit_movie_path(m), method: 'get', class: 'btn btn-primary btn-sm btn-space' %>
<%= button_to "Delete movie", movie_path(m), method: 'delete', controller: 'movies', class: 'btn btn-danger btn-sm btn-space', data: { confirm: "Are you sure?"} %>
</span>
</div>
</div>
</div>
<% end %>
</div>
The idea is that when the button is pressed, sort_by: 'title' is passed into my params, then I call the order_list method on my movies in that list, and then the view is updated with a sorted list. As of right now, the params look good when the button is clicked, but the view isn't updating. What am I missing? Is there a better way to do this?
When calling list_path helper you need to pass list id as an argument. See the docs. Additional params are allowed, but after required ones.
Changing your link to:
<%= link_to "Sort By Title", list_path(#list.id, sort_by: 'title'), class: 'btn btn-secondary btn-sm btn-space' %>
should fix it.
The other problem, in your controller you call order_list method for movies collection of the list, whereas it is defined for List model itself. I think you need to change it to #list.order_list(params[:sort_by])
One more thing: you call order_list method but does not use its result. So sorted movies are just wasted. To fix it you need to store it to instance variable and reuse in the view:
#movies = #list.order_list(params[:sort_by])
Currently learning through a Udemy Course but changed the lecture to something I am more interested in developing.
Project Basis:
- using Gem Flightstats-flex to pull flight data
- trying to display associated info from a search query
Current setup
app/controllers/trackers_controller.rb
class TrackersController < ApplicationController
def search
#tracker = FlightTracker.new_from_lookup(params[:tracker])
render 'users/my_tracker'
end
end
app/models/flight_tracker.rb
class FlightTracker < ActiveRecord::Base
self.table_name='trackers'
def self.new_from_lookup(tracker)
flight_track = FlightStats::FlightStatus.by_flight_id(tracker)
# flight_position = FlightStats::FlightStatus.track_by_flight_id(tracker)
end
This is where the problem happens, when I remove # from flight_position = FlightStats::FlightStatus.track_by_flight_id(tracker)
the results overwrite the top
if I use the line only it displays and vice versa for the top line
app/views/users/my_tracker.html.erb the data does render
<h1>
My Tracker
</h1>
<h3>Search for Flights</h3>
<div id="tracker-lookup">
<%= form_tag search_trackers_path, method: :get, id: "tracker-lookup-form" do %>
<div class="form-group row no-padding text-center col-md-12">
<div class="col-md-10">
<%= text_field_tag :tracker, params[:tracker],
placeholder: "Stock ticker symbol", autofocus: true,
class: "form-control search-box input-lg" %>
</div>
<div class="col-md-2">
<%= button_tag(type: :submit, class: "btn btn-lg btn-success") do %>
<i class="fa fa-search"></i> Look up a tracker
<% end %>
</div>
</div>
<% end %>
</div>
<div class="well results-block">
<%=#tracker.inspect%>
<strong>ID: </strong> <%#= #tracker&.flight_id %>
<strong>Code: </strong> <%#= #tracker&.carrier_fs_code %>
<strong>Number: </strong> <%#= #tracker&.flight_number %>
<strong>Departure: </strong> <%#= #tracker&.departure_airport_fs_code %>
<strong>Arrival: </strong> <%#= #tracker&.arrival_airport_fs_code %>
<%# <strong>Departure Terminal: </strong> <%= #tracker&.departure_terminal %> %>
<%=#position.inspect%>
</div>
So when an user searches for a .by_flight_id , I want it to show the related data for .track_by_flight_id
Hoping to move to the next stage of more data associations after a query is completed.
As illustration for my comment
def self.new_from_lookup(tracker)
flight_track = FlightStats::FlightStatus.by_flight_id(tracker)
flight_position = FlightStats::FlightStatus.track_by_flight_id(tracker)
OpenStruct.new(flight_track: flight_track, flight_position: flight_position)
end
Then you'll need to rewrite template my_tracker.html.erb to handle new data structure
I am trying to have a photo upload section in my room listing. when I try to click on the photos I get this error
undefined method 'count' for nil:NilClass rails <% if #photos.count > 0 %> .
I have added a photo_upload.html.erb page and a _room_menu partial but still I get the error.
here's my code:
photos_controller.rb
class PhotosController < ApplicationController
def create
#room = Room.find(params[:room_id])
if params[:images]
params[:images].each do |img|
#room.photos.create(image:img)
end
#photos = #room.photos
redirect_back(fallback_location:request.referer, notice: "Saved...")
end
end
end
**views/rooms/photo_upload.html.erb**
<div class="row">
<div class="col-md-3">
<%= render 'room_menu' %>
</div>
<div class="col-md-9">
<div class="panel panel-default">
<div class="panel-heading">
Photos
</div>
<div class="panel-body">
<div class="container">
<div class="row">
<div class="col-md-offset-3 col-md-6">
<!-- PHOTOS UPLOAD GOES HERE -->
<%= form_for #room, url: room_photos_path(#room), method: 'post', html: {multipart: true} do |f| %>
<div class="row">
<div class="form-group">
<span class="btn btn-default btn-file text-babu">
<i class="fa fa-cloud-upload" aria-hidden="true"></i> Select Photos
<%= file_field_tag "images[]", type: :file, multiple: true %>
</span>
</div>
</div>
<div class="text-center">
<%= f.submit "Add Photos", class: "btn btn-form" %>
</div>
<% end %>
</div>
</div>
<div id="photos"><%= render 'photos/photos_list' %></div>
</div>
</div>
</div>
</div>
</div>
views/rooms/_room_menu.html.erb
<ul class="sidebar-list">
<li class="sidebar-item">
<%= link_to "Listing", listing_room_path, class: "sidebar-link active" %>
<span class="pull-right text-babu"><i class="fa fa-check"></i></span>
</li>
<li class="sidebar-item">
<%= link_to "Pricing", pricing_room_path, class: "sidebar-link active" %>
<% if !#room.price.blank? %>
<span class="pull-right text-babu"><i class="fa fa-check"></i></span>
<% end %>
</li>
<li class="sidebar-item">
<%= link_to "Description", description_room_path, class: "sidebar-link active" %>
<% if !#room.listing_nam.blank? %>
<span class="pull-right text-babu"><i class="fa fa-check"></i></span>
<% end %>
</li>
<li class="sidebar-item">
<%= link_to "Photos", photo_upload_room_path, class: "sidebar-link active" %>
<% if !#room.photos.blank? %>
<span id="photo_check" class="pull-right text-babu"><i class="fa fa-check"></i></span>
<% end %>
</li>
<li class="sidebar-item">
<%= link_to "Amenities", amenities_room_path, class: "sidebar-link active" %>
<span class="pull-right text-babu"><i class="fa fa-check"></i></span>
</li>
<li class="sidebar-item">
<%= link_to "Location", location_room_path, class: "sidebar-link active" %>
<% if !#room.address.blank? %>
<span class="pull-right text-babu"><i class="fa fa-check"></i></span>
<% end %>
</li>
</ul>
<hr/>
You can't call .count on a nil. #photos must be instantiated first. You controller doesn't appear to instantiate #photos at all. I can't see where else in your code you're calling #photos but where it's getting called, the instance variable has not yet be defined. Your controller create method only shows it happens if params[:images] is present, if otherwise it will be nil.
Try to instantiate #photos outside the if block.
def create
#room = Room.find(params[:room_id])
#photos = #room.photos
if params[:images]
params[:images].each do |img|
#room.photos.create(image: img)
end
redirect_back(fallback_location:request.referer, notice: "Saved...")
end
end
UPDATE: Ruby 2.3+ you can use safe navigation with & :
def create
#room = Room.find(params[:room_id])
params[:images]&.each{|img| #room.photos.create(image: img)}
redirect_back(fallback_location: request.referer, notice: "Saved...")
end
Or why bother using separate #photos in view when you should be able to just call #room.photos in it's place.
Instead of calling .count as your conditional in the view, use #room.photos.present?
One more suggestion is to prefer to use positive if case. so change
if !#room.photos.blank?
# better to use this below
if #room.photos.present?
Also, one would assume before a create action, you need a new action in your controller where one would expect #photos to be defined if it really needs be isolated from #room.photos. This is standard MVC in rails, but not sure if you've posted all of your code correctly so I'm guessing here.
The people above have already given great explanations as to why you can't call a method on a nil class. In addition, maybe the following code will help in your situation:
<% if !#photos.nil? && #photos.count > 0 %>
<% if #photos.count > 0 %>
If this fails with an error 'undefined method for nil class', then it means #photos is nil, and you therefore can't perform any methods on it. Where are you calling it? You've not included it in your code.
When you click on the link, look at your server logs and it will tell you which controller action you are hitting. Whichever action you're hitting, is where you'll need to define #photos.
If it is photos#create (the controller action you listed above) then it means that #room.photos is nil. That's unlikely, as it would almost certainly return an empty active record relation if anything, so your problem is not defining #photos in the controller and action you're using at that time.
is there a way i can use a form to update a user's points in rails with a simple form that takes in the name and the points I want to append?
Heres the link to the app i made : enter link description here
my view for the index is :
<div class="container">
<h1 class="text-center">Listing Students</h1>
<div class ="jumbotron">
<table class="table table-hover">
<thead>
<tr>
<th>Name</th>
<th>Points</th>
</tr>
</thead>
<% #users.each do |user| %>
<tr>
<td><%= user.name %></td>
<td><%= user.points %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Delete', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
<br>
<%= link_to 'New Student', new_user_path, class:'btn btn-primary' %>
</div>
I tried using the code in my edit page :
<div class="container">
<div class=" text-center">
<div class="col-md-6 col-md-offset-3">
<div class= "well well-lg">
<%= render 'form' %>
<%= link_to 'Back', users_path, class:"back" %>
</div>
</div>
</div>
</div>
to render the form in the index but it gives me an error of #user can not be nill
I simply need to update the users points in the index page , it would be great if i can greate a modal to appear and then type in the name and edit it. Ive been working on this for hours and seem to update it .
Sure, you could use simple_form or form_for. Or you could do inplace editing. Your question is not very precise as to what exactly you need.
UPDATE 1:
Assuming that you have added simple_form gem to the gemfile, and that you have something like this in the routes.rb : resources :users, then edit view of the UsersController could look something like this:
#in controller
def edit
#user = User.find(params['id'])
end
And the view:
<%= simple_form_for #user do |f| %>
<%= f.input :name %>
<%= f.input :points %>
<%= f.button :submit %>
<% end %>
Please try it and let me know if it works for you (the edit view; in order to persist, you will need and update action as well).
Add a div on index page to open modal popup:
<div class='modal_popup>
</div>
For updating name and points of user on index page, you have to change edit link like this:
<%= link_to 'Edit', edit_user_path(user), remote: true %>
Controller changes:
def edit
#user = User.find(params[:id])
end
_modal.html.erb
<div class="modal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title">Modal title</h4>
</div>
<%= form_for #user, remote: true do |f| %>
<div class="modal-body">
<%= f.text_field :name %>
<%= f.text_field :points %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<%= f.submit 'Update', class: "btn btn-primary" %>
</div>
<% end %>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
edit.js.erb
$('.modal_popup').html("<%= j(render partial: '/users/modal') %>");
$('.modal').show();
After updating user in update.js.erb add below lines of code:
$('.modal').hide();
window.location.reload();
Hope this may help..