Vehicles_controller.rb
class VehiclesController < ApplicationController
before_action :set_vehicle, only: [:show, :edit, :update, :destroy]
load_and_authorize_resource
# skip_before_action :verify_authenticity_token
# GET /vehicles
# GET /vehicles.json
def index
#q = Vehicle.search(params[:q])
#vehicles = #q.result(:distinct => true).order_by([:updated_at, :desc]).page(params[:page]).per(5)
#vehicle = Vehicle.new
end
# GET /vehicles/1
# GET /vehicles/1.json
def show
end
# GET /vehicles/new
def new
end
# GET /vehicles/1/edit
def edit
end
# POST /vehicles
# POST /vehicles.json
def create
params[:vehicle][:name] = params[:vehicle][:name].upcase if !params[:vehicle][:name].nil?
#vehicle = Vehicle.new(vehicle_params)
#vehicles = Vehicle.all.order_by([:updated_at, :desc]).page(params[:page]).per(5)
respond_to do |format|
if #vehicle.save
format.html { redirect_to :back, notice: 'Vehicle was successfully created.' }
format.json { render action: 'index', status: :created, location: #vehicle }
format.js
else
format.js
format.html { render action: 'new' }
format.json { render json: #vehicle.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /vehicles/1
# PATCH/PUT /vehicles/1.json
def update
params[:vehicle][:name] = params[:vehicle][:name].upcase if !params[:vehicle][:name].nil?
respond_to do |format|
if #vehicle.update(vehicle_params)
format.html { redirect_to #vehicle, notice: 'Vehicle was successfully updated.' }
format.json {render json: #vehicle, status: :ok}
else
format.html { render action: 'edit' }
format.json { render json: #vehicle.errors, status: :unprocessable_entity }
end
end
end
# DELETE /vehicles/1
# DELETE /vehicles/1.json
def destroy
#vehicle.destroy
respond_to do |format|
format.html { redirect_to vehicles_url, notice: "#{#vehicle.name} deleted successfully" }
format.json { head :no_content }
format.js { render :layout => false}
end
end
def vehicle_search
#q = Vehicle.search(params[:q])
#vehicles = #q.result(:distinct => true).order_by([:updated_at, :desc]).page(params[:page]).per(5)
respond_to do |format|
format.html
format.js
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_vehicle
#vehicle = Vehicle.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def vehicle_params
params.require(:vehicle).permit(:name, :created_at, :updated_at)
end
end
index.html.erb
<% #vehicles.each do |vehicle| %>
<tr>
<td><%= best_in_place vehicle,:name, class: "v_name", id: vehicle.id%></td>
<td><%= link_to '<i class="fa fa-trash-o"></i>'.html_safe, vehicle, method: :delete, remote: true, data: { confirm: "Are you sure to delete <b>\"#{vehicle.name}\"?</b>", commit: "OK" }, title: "Delete Vehicle", class: "btn btn-danger delete_vehicle" %>
</td>
</tr>
<%end%>
vehicle.rb
class Vehicle
include Mongoid::Document
include Mongoid::Timestamps
field :name, type: String
validates :name, presence: true, uniqueness: true, :format => {:with => /[1-9a-zA-Z][0-9a-zA-Z ]{3,}/}
has_many :pre_processings
has_many :batch_counts
end
destroy.js.erb
$('.delete_vehicle').bind('ajax:success', function() {
$(this).closest('tr').fadeOut();
});
$(".alert").show();
$(".alert").html("Vehicle \"<b><%=#vehicle.name %></b>\" deleted successfully.")
$(".alert").fadeOut(5000);
Here i am using destroy.js.erb to delete vehicle name. It works fine.
Here i am using Inline Edit for Best_in_place. After update the Vehicle name, The ajax alert shows previous vehicle name. Not update vehicle name. So how to show updated vehicle name alert.
$(".alert").html("Vehicle \"<b><%=#vehicle.name %></b>\" deleted successfully.")
The above alert i will show current vehicle name to delete. But if i update using inline edit after i want to delete i'll shows previous record.
Example:
Vehicle Name: MH P5 2312 , I want to delete it, The alert shows are you delete "MH P5 2312 " Vehicle.
After inline edit i will change Vehicle Name: AP 16 1234, So i want to delete Vehicle Name: AP 16 1234, but the ajax alert shows, Vehicle Name: MH P5 2312 delete vehicle name.
Advance Thanks.
This is because you need to update the alert message on ajax request success
in your destroy.js.erb
you should ditch the .erb and fetch the car name from an html element instead
your js code should be as the following:
$('.delete_vehicle').bind('ajax:success', function() {
var vehicleName = $('vehicle_link').data('vehicle_name');
// here I assume that you have a link for initiating the delete process and you can add an attribute to this anchor tag element called data-vehicle_name and set its value to the car name.
$(this).closest('tr').fadeOut();
$(".alert").show();
$(".alert").html("Vehicle \"<b>" + vehicleName + "</b>\" deleted successfully.");
$(".alert").fadeOut(5000);
});
Firstly, if you're going to use the ajax:success callback (which you don't in this instance), you'll need to bind the alert functions to it:
$('.delete_vehicle').on('ajax:success', function() {
$(this).closest('tr').fadeOut();
$(".alert").show().html("Vehicle \"<b><%=#vehicle.name %></b>\" deleted successfully.").fadeOut(5000);
});
Secondly, if you're not getting an updated #vehicle.name because - I think - your Rails instance will have already rendered it. I'm not exactly sure why, but the key will be to pass your data through the ajax request if you were still going to use it:
#app/controllers/vehicles_controller.rb
class VehiclesController < ApplicationController
def destroy
...
format.js { render :layout => false, json: #vehicle }
end
end
#app/assets/javascripts/application.js
$('.delete_vehicle').on('ajax:success', function(event, data, status, xhr) {
vehicle = JSON.parse(data);
$(this).closest('tr').fadeOut();
$(".alert").show().html("Vehicle \"<b>" + + "</b>" deleted successfully.").fadeOut(5000);
});
--
Bottom line is that js.erb is meant to give you actionable Javascript functionality from the controller action. I think your main problem is you're using ajax within this, likely causing a conflict.
Above is how I'd use Ajax (IE put the code in the javascript assets folder); if you wanted to use destroy.js.erb still, you could use the following:
#app/views/vehicles/destroy.js.erb
$("<%= #vehicle.id %>").closest('tr').fadeOut();
$(".alert").show();
$(".alert").html("Vehicle \"<b><%=#vehicle.name %></b>\" deleted successfully.")
$(".alert").fadeOut(5000);
Related
I have problem with my HTML sortable update in rails 6. I drag and drop some portfolio images through web page and that is working good but when i want to update the web page with updated position i got NoMethodError (undefined method `each' for nil:NilClass):
I use this script for HTML Sortable
https://github.com/jordanhudgens/devcamp-portfolio/blob/master/app/assets/javascripts/html.sortable.js
portfolio_controller:
class PortfoliosController < ApplicationController
before_action :set_portfolio_item, only: [:edit, :show,:update, :destroy]
layout "portfolio"
access all: [:show, :index, :angular], user: {except: [:destroy, :new, :create, :update, :edit]}, site_admin: :all
def index
#portfolio_items = Portfolio.by_position
end
def sort
params[:order].each do |key, value|
Portfolio.find(value[:id]).update(position: value[:position])
end
head :ok
end
def angular
#angular_portfolio_items = Portfolio.angular
end
def new
#portfolio_item = Portfolio.new
3.times { #portfolio_item.technologies.build }
end
def create
#portfolio_item = Portfolio.new(portfolio_params)
respond_to do |format|
if #portfolio_item.save
format.html { redirect_to portfolios_path, notice: 'Your Portfolio item is now live.' }
else
format.html { render :new }
end
end
end
def edit
end
def update
respond_to do |format|
if #portfolio_item.update(portfolio_params)
format.html { redirect_to portfolios_path, notice: 'The Record successfully updated.' }
else
format.html { render :edit }
end
end
end
def show
end
def destroy
#Destroy/delete the record
#portfolio_item.destroy
#Redirect
respond_to do |format|
format.html { redirect_to portfolios_url, notice: 'Record was removed' }
end
end
private
def set_portfolio_item
#portfolio_item = Portfolio.find(params[:id])
end
def portfolio_params
params.require(:portfolio).permit(:title,
:subtitle,
:body,
technologies_attributes: [:name]
)
end
end
routes.rb:
Rails.application.routes.draw do
devise_for :users, path: '', path_names: { sign_in: 'login', sign_out: 'logout', sign_up: 'register'}
resources :portfolios, except: [:show] do
put :sort, on: :collection
end
get 'angular-items', to: 'portfolios#angular'
get 'portfolio/:id', to: 'portfolios#show', as: 'portfolio_show'
get 'about-me', to: 'pages#about'
get 'contact', to: 'pages#contact'
resources :blogs do
member do
get :toggle_status
end
end
root to: 'pages#home'
end
Here is my portfolio.js :
var ready, set_position;
ready = void 0;
set_position = void 0;
set_position = function() {
$(".card").each(function(i) {
$(this).attr('data-pos', i + 1);
});
};
ready = function() {
set_position();
$('#sortable').sortable();
$('#sortable').sortable().bind('sortupdate', function(e, ui) {
var updated_order;
updated_order = [];
set_position();
$(".card").each(function(i) {
updated_order.push;
({
id: $(this).data('id'),
position: i + 1
});
});
$.ajax({
type: 'PUT',
url: '/portfolios/sort',
data: {
order: updated_order
}
});
});
};
$(document).ready(ready);
_portfolio_item.html.erb :
<div class="card" data-id="<%= portfolio_item.id %>">
<%= image_tag portfolio_item.thumb_image unless portfolio_item.thumb_image.nil? %>
<p class="card-text">
<span>
<%= link_to portfolio_item.title, portfolio_show_path(portfolio_item) %>
</span>
<%= portfolio_item.subtitle %>
</p>
</div>
Thank you for your helps!
The only place I see an each statement is in the sort method of your PortfoliosController.
params[:order].each
You need to set your params[:order] or prevent this error from happening by checking if it is set. You could use the save navigation operator:
params[:order]&.each
Or you could check if the order parameter is set with the present? method.
if params[:order].present?
params[:order]&.each
I am building a rails app that creates a like(create) or unlike(destroy), on a link click with a remote: true ajax request
The Post goes through and the transaction is committed but the the js response is not going through and I receive a Error in the server console
No template found for ForumThreads::ForumPosts::LikesController#create, head :no_content
the view structure is
forum_threds/show.html.haml
....
= render #forum_thread.forum_posts
....
to render a view of every post that is in the thread
than
forum_posts/_forum_post.html.haml
....
%div{id: "fourm_post_#{forum_post.id}" }
= render partial: "forum_posts/likes", locals: { post: forum_post }
....
which is rendering
forum_posts/_likes.html.haml
- if user_signed_in? && current_user.likes?(post)
= link_to "UnLike", forum_post_likes_path(post), method: :delete,
remote: true
- else
= link_to "Like", forum_post_likes_path(post), method: :post, remote:
true
and my controller is
class ForumThreads::ForumPosts::LikesController < ApplicationController
before_action :authenticate_user!
before_action :set_forum_post
before_action :set_forum_thread
def create
#forum_post.likes.where(user_id: current_user.id).first_or_create
respond_to do |format|
format.js
format.html { redirect_to #forum_thread}
end
end
def destroy
#forum_post.likes.where(user_id: current_user.id).destroy_all
respond_to do |format|
format.js
format.html { redirect_to #forum_thread}
end
end
private
def set_forum_thread
#forum_thread = ForumThread.find(#forum_post.forum_thread_id)
end
def set_forum_post
#forum_post = ForumPost.find(params[:forum_post_id])
end
end
With remote: false this works as expected with the page reload but when i put remote: true I receive the no template error
my file structure for the views
forum_threads/
show.html.haml
forum_posts/
show.html.haml
_likes.html.haml
likes/
create.js.erb
destroy.js.erb
and the create.js.erb and destroy.js.erb
$("#forum_post_<%= forum_post.id %>").html(<%= j render
'forum_posts/likes' %>);
but i know that this file isn't even being called
is there a way from the format.js that i may be able to call the file i need directly? or something?
I am trying to include FullCalendar into my rails app. But I am having difficulty with saving after drag-and-drop.
I have 2 models - Event and Workout. Under event, there is workout.
I am able to get the full calendar up and running and save events, but when I drag and drop, then refresh, the events would revert to their original time.
In my console, it says:
Couldn't find Event with 'id'=update.
When the events are created and saved through a form, they are properly displayed and saved on calendar. It's just when I try to drag-and-drop.
Here is my Event controller.
class EventsController < ApplicationController
before_action :set_event, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
def index
#events = current_user.events
end
def show
#event = Event.find(params[:id])
end
def new
#event = current_user.events.new
end
def edit
#event = current_user.events.find(params[:id])
end
def create
#event = current_user.events.new(event_params)
respond_to do |format|
if #event.save
format.html { redirect_to #event, notice: 'Event was successfully created.' }
format.json { render :show, status: :created, location: #event }
else
format.html { render :new }
format.json { render json: #event.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #event.update(event_params)
format.html { redirect_to #event, notice: 'Event was successfully updated.' }
format.json { render :show, status: :ok, location: #event }
else
format.html { render :edit }
format.json { render json: #event.errors, status: :unprocessable_entity }
end
end
end
def destroy
#event.destroy
respond_to do |format|
format.html { redirect_to events_url, notice: 'Event was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_event
#event = Event.find(params[:id])
end
def event_params
params.require(:event).permit(:title, :description, :start_time, :end_time, :workouts_attributes => [:id, :name, :category, :_destroy])
end
end
Below is application.js file that controls the calendar.
$(document).on('turbolinks:load', function() {
$('#calendar').fullCalendar({
editable: true,
events: '/events.json',
eventDrop: function(event, delta) {
$.ajax({
type: "PUT",
url: '/events/update',
dataType: 'json',
data: {id:event.id, start:event.start_time, end: event.end_time}
});
},
});
});
When I try to drag and drop, I get a message below:
ActiveRecord::RecordNotFound (Couldn't find Event with 'id'=update):
app/controllers/events_controller.rb:74:in `set_event'
When I check my console, all the events have IDs. But I'm guessing maybe when the event is being drag-and-dropped, the new event doesn't have an ID?
Rails app is assuming update as :id when you are hitting this URL /events/update
$ rake routes
event PUT /events/:id(.:format) events#update
change the url in ajax request to
$.ajax({
type: 'PUT',
url: '/events/' + event.id,
dataType: 'json',
data: { event: { start_time:event.start_time, end_time: event.end_time } }
});
I have been following the Railscast raffler tutorial and am trying to create a new view in my users controller which will use Angular to display a list of all users with the role of "user" from the user table (I haven't implemented this yet), and then randomly select one of them to become winner (a winner field will be boolean checked to true). At the moment, I have decided to add a new method in the users controller, "raffle", and of course a corresponding view to show this. However, when I open users/raffle, I get the following error, and I seem to have followed the proper way of defining a route before resources:
No route matches [GET] "/raffle"
(Perhaps there are more optimal ways to do this, but my request is that I please use angular to achieve this because I really need to learn it.)
Here is my routes.rb:
Rails.application.routes.draw do
resources :scholarships
devise_for :users, :controllers => { registrations: 'registrations' }
get 'users/raffle' => 'users#raffle'
resources :users
get 'static_pages/instructions'
get 'static_pages/about'
get 'static_pages/contact'
get 'static_pages/landing_page'
root 'static_pages#landing_page'
end
Here is my users controller:
class UsersController < ApplicationController
include Devise::Controllers::Helpers
before_action :authenticate_user!
#Users who are not signed in cannot view users list
before_action :set_user, only: [:show, :edit, :update, :destroy]
load_and_authorize_resource
respond_to :html, :json, only: [:raffle]
# GET /users
# GET /users.json
def index
#users = User.all
end
def raffle
end
# GET /users/1
# GET /users/1.json
def show
end
# GET /users/new
def new
#user = User.new
end
# GET /users/1/edit
def edit
#user = current_user
end
# POST /users
# POST /users.json
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1
# PATCH/PUT /users/1.json
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { render :show, status: :ok, location: #user }
else
format.html { render :edit }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
#user.destroy
respond_to do |format|
format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
#Never trust paramaters from the scary internet, man.
def user_params
params.require(:user).permit(:first_name, :last_name, :email)
end
end
My javascript file with angular:
var rafflerApp = angular.module('rafflerApp', ["ngResource"]);
rafflerApp.controller('rafflerController', function($scope, $resource) {
User = $resource("/users/:id", {id: "#id"},{update: {method: "PUT"}})
$scope.users = User.query()
//Draw a New Winner
$scope.drawWinner = function(){
pool=[];
angular.forEach($scope.users,function(user){
if(!user.winner){
pool.push(user) ;
}
});
if(pool.length >0) {
user = pool[Math.floor(Math.random()*pool.length)];
user.winner = true;
user.$update();
$scope.lastWinner = user;
}
}
});
My raffle.html.erb file:
<% if user_signed_in? && current_user.role == "Admin" %>
<h1 class="center">Winner Raffler</h1>
<h4 class="center">To select a winner for this year's scholarship, simply click "choose winner" below</h4>
<div ng-controller="rafflerController">
<ul>
<li ng-repeat="user in users">
{{user.first_name}}
<span ng-show="user.winner">Winner</span>
</li>
</ul>
</div>
<button ng-click="drawWinner()">Draw Winner</button>
<% end %>
Users schema:
create_table "users", force: :cascade do |t|
t.string "first_name"
t.string "last_name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.integer "role", default: 1
t.boolean "winner", default: false
t.integer "scholarship_id"
end
Thank you in advance.
Modify your routes.rb as follow:
Rails.application.routes.draw do
# ...
# get 'users/raffle' => 'users#raffle' <-- remove this line
resources :users do
get :raffle, on: :collection
end
#...
end
Update: My Github Repository https://github.com/Marc585/smartforce2
i just finished the onemonthrails tutorial. at the last chapter its about endless scrolling. i tripple checked my code but it just doesn't work. I don't get an error or anything. It just doesn't do anything. I'm building a pinterest clone and after i scroll to the bottom it should load the next page of pins.
This is my pins.js.coffee
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
jQuery ->
$('#pins').imagesLoaded ->
$('#pins').masonry itemSelector: ".box"
if $('.pagination').length
$(window).scroll ->
url = $('.pagination .next_page a').attr('href')
if url && $(window).scrollTop() > $(document).height() - $(window).height() - 50
# What to do at the bottom of the page
$('.pagination').text("Fetching more pins...")
$.getScript(url)
$(window).scroll()
This is my index.js.erb
$boxes = $('<%= j render(#pins) %>')
$('#pins').append( $boxes ).imagesLoaded( function(){
$('#pins').masonry( 'reload');
});
<% if #pins.next_page %>
$('.pagination').replaceWith('<%= j will_paginate(#pins) %>');
<% else %>
$('.pagination').remove();
<% end %>
This is my pins controller:
class PinsController < ApplicationController
before_filter :authenticate_user!, except: [:index]
# GET /pins
# GET /pins.json
def index
#pins = Pin.order("created_at desc").page(params[:page]).per_page(20)
respond_to do |format|
format.html # index.html.erb
format.json { render json: #pins }
format.js
end
end
# GET /pins/1
# GET /pins/1.json
def show
#pin = Pin.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #pin }
end
end
# GET /pins/new
# GET /pins/new.json
def new
#pin = current_user.pins.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #pin }
end
end
# GET /pins/1/edit
def edit
#pin = current_user.pins.find(params[:id])
end
# POST /pins
# POST /pins.json
def create
#pin = current_user.pins.new(params[:pin])
respond_to do |format|
if #pin.save
format.html { redirect_to #pin, notice: 'Pin was successfully created.' }
format.json { render json: #pin, status: :created, location: #pin }
else
format.html { render action: "new" }
format.json { render json: #pin.errors, status: :unprocessable_entity }
end
end
end
# PUT /pins/1
# PUT /pins/1.json
def update
#pin = current_user.pins.find(params[:id])
respond_to do |format|
if #pin.update_attributes(params[:pin])
format.html { redirect_to #pin, notice: 'Pin was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #pin.errors, status: :unprocessable_entity }
end
end
end
# DELETE /pins/1
# DELETE /pins/1.json
def destroy
#pin = current_user.pins.find(params[:id])
#pin.destroy
respond_to do |format|
format.html { redirect_to pins_url }
format.json { head :no_content }
end
end
end
Error Message from my developer tools
https://www.dropbox.com/s/odqknmw7np1f4cv/Bildschirmfoto%202013-08-31%20um%2014.34.40.png
You are missing
format.js in your show action in the pins_controller.rb. This is from the onemonth rails notes
Note: You'll have to create an analogous show.js.erb and add the format.js option to your users#show action to get endless scroll to work on users' profile pages as well
def show
#pin = Pin.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #pin }
format.js
end
end
Your show.js.erb should look like this
boxes = $('<%= j render(#pins) %>')
$('#pins').append( $boxes ).imagesLoaded( function(){
$('#pins').masonry( 'reload');
});
<% if #pins.next_page %>
$('.pagination').replaceWith('<%= j will_paginate(#pins) %>');
<% else %>
$('.pagination').remove();
<% end %>