When I delete an object with #model.destroy method, it tries to redirect to the deleted object. How can I change the routing to redirect to root instead?
My delete method:
deleteBook: (ev) ->
#model.destroy success: ->
router.navigate "",
trigger: true
Router:
Router = Backbone.Router.extend(routes:
"": "home"
)
Update:
Full error:
GET http://localhost:3000/ 404 (Not Found) jquery.js?body=1:8707
send jquery.js?body=1:8707
jQuery.extend.ajax jquery.js?body=1:8137
Backbone.sync backbone_rails_sync.js?body=1:65
_.extend.destroy backbone.js?body=1:428
Backbone.View.extend.deleteBook main.js?body=1:32
jQuery.event.dispatch jquery.js?body=1:5096
elemData.handle
Update2:
My coffeescript file:
$(document).ready ->
window.Book = Backbone.Model.extend(
urlRoot: '/books/', idAttribute: 'id'
)
BooksView = Backbone.View.extend(
el: ".books"
addOne: (model) ->
view = new BookView(model: model)
$("ul.books").append view.render()
)
Router = Backbone.Router.extend(routes:
"": "home"
)
Books = Backbone.Collection.extend(
model: Book
url: '/books/'
)
BookView = Backbone.View.extend(
tagName: "li"
events:
"click .delete": "deleteBook"
deleteBook: (ev) ->
#model.destroy()
render: ->
##$el.append('Some text <button type="button" class="delete">Delete</button>')
title = #model.get("title")
author = #model.get("author")
year = #model.get("year")
link = "books/"+#model.get("id")
a = document.createElement('a')
a.href = link
show = 'Show'
row = title + ", " + author + ", " + year + " " + show
$(#el).html row
#$el.append(' <button type="button" class="delete">Delete</button>')
)
books = new Books()
books.url = "books.json"
books.fetch success: ->
books_view = new BooksView({})
_.each books.models, (model) ->
books_view.addOne model
It looks like it does not even look at the success function as, either it tries to redirect to the path were deleted object was.
Or maybe it still references deleted object and it tries to use GET method after delete somehow?..
Related
I'm trying to store multiple values retrieved from a JSONP request into my rails database so I can show the different results later.
I've created a function in my controller like this,
movieAdd.trailer(movie.id)
.then(function(response){
$scope.youtubeTrailer = response;
console.log ($scope.youtubeTrailer)
This requests the trailer service in my movieService.js,
var service = {};
var baseUrl = 'http://api.themoviedb.org/3/movie/';
function httpPromise (url) {
var deferred = $q.defer();
$http({
method:'JSONP',
url: url
})
.success(function(data){
deferred.resolve(data);
})
.error(function(){
deferred.reject();
});
return deferred.promise;
}
service.trailer = function(youtube_link){
return httpPromise(
baseUrl + youtube_link + '/videos?api_key=a8f7039633f2065942c**a28d7cadad4&callback=JSON_CALLBACK'
)
};
And I store the results in the youtubeTrailer scope.
Then I have a create function,
createMovie.create({
release_date: $scope.movieListID.release_date,
youtube_link: $scope.youtubeTrailer.key,
imdb_rating: $scope.movieImdbRating.imdbRating,
title: $scope.movieListID.original_title,
image: $scope.movieListID.poster_path,
movie_id: $scope.movieListID.id
}).then(init);
I've added the param to my movies_controller.rb
def movie_params
params.require(:movie).permit(:title, :image, :release_date, :youtube_trailer, :imdb_rating, :movie_id)
end
And I've created a column in my movies table
t.string "youtube_trailer"
But when I check my movies.json it says youtube_trailer":null
To recap, I get this kind of output,
{"id":1893,"results":[
{"id":"533ec65ac3a3685448000a24","iso_639_1":"en","key":"bD7bpG-zDJQ","name":"Trailer 1","site":"YouTube","size":720,"type":"Trailer"},
{"id":"533ec65ac3a3685448000a25","iso_639_1":"en","key":"UgDhFgSTPIw","name":"Trailer 2","site":"YouTube","size":720,"type":"Trailer"}
]}
And I'm trying to store both key values in my database so I can use them later.
You are expecting youtube_trailer but create this field as youtube_link. Please try to match the variable names.
Context: I have a Rails backend serving as an API to an Angular.JS front-end application.
Task: I want to retrieve all of the records of different species of "dinosaurs" from the Rails backend. Since there are over 500 records, I want to only get 30 species at a time.
My current approach: I am using the will_paginate gem in my Rails index controller action for the dinosaurs_controller. I have it running like this.
def index
#dinosaurs = Dinosaur.paginate(:page => params[:page], :per_page => 30)
end
In my Angular code:
I have a module called DinoApp and am using ngresource to create an Entry resource
app = angular.module("DinoApp", ["ngResource"])
app.factory "Entry", ["$resource", ($resource) ->
$resource("/api/v1/dinosaurs/:id", {id: "#id"}, {update: {method: "PUT"}} )
]
My Angular controller looks like this:
#MainController = ["$scope", "Entry", ($scope, Entry) ->
$scope.entries = Entry.query({page: 1})
$scope.viewPost = (dinosaurId) ->
]
This line of code would hit the API at dinosaurs_controller's index action and will only return 30 species of "dinosaurs" at a time:
$scope.entries = Entry.query({page: 1})
Now - how would I get angular.js to show a next page button and append the next page to the view?
I created a directive for this, which might be helpful:
https://github.com/heavysixer/angular-will-paginate
You can use a counter for the number of pages that gets incremented each time your controller gets called.
var counter = 1;
$scope.loadPage = function() {
$scope.entries = Entry.query({page: counter})
counter += 1 ;
}
And have a button that refer to that next page.
<button ng-click="loadPage()">Next page</button>
I have this in my html template. I want the button to fire the showMore function when clicked.
<button ng-click="showMore(secondPage)">Show More</button>
This is the controller. I'm not sure why $scope.nextPage will increment up everywhere except for at $scope.secondPage. I want $scope.secondPage to do fire on the first click Entry.query({page: 2}) then fire Entry.query({page: 3}) on the next click. But right now it keeps firing page 2.
#MainController = ["$scope", "Entry", ($scope, Entry) ->
$scope.entries = Entry.query({page: 1})
$scope.nextPage = 2
$scope.secondPage = Entry.query({page: $scope.nextPage})
$scope.showMore = (secondPage) ->
i = 0
while i < secondPage.length
$scope.entries.push(secondPage[i])
i++
$scope.nextPage++
console.log("nextpage" + $scope.nextPage)
]
I am using coffeescript. I don't fully understand why the page number in $scope.secondPage is not incrementing.
I'd do:
<button ng-click="showMore()">Show More</button>
#MainController = ["$scope", "Entry", ($scope, Entry) ->
$scope.entries = []
current_page = 1
$scope.showMore = ->
on_success = (entries)->
$scope.entries = $scope.entries.concat entries
current_page = current_page + 1
Entry.query {page: current_page}, on_success
$scope.showMore()
]
In my rails controller I have something like this:
def index
provider_id = params[:provider] ||= 'all'
thera_class = params[:therapeutic_class] ||= 'all'
med_name = params[:medication_name] ||= 'all'
In the JavaScript side I am passing these params as URL query params so when it gets called it goes to this Index action method:
window.open("http://localhost:3000/pharmacy/patients?provider="+provider_id+"&"+"therapeutic_class="+thera_class+"&"+"medication_name="+medication_name);
The problem is the JavaScript values I am passing if they don't have a value and are undefined they will be passed as undefined.
I am more concerned to know is it too much architecturally wrong that I am doing this? What is the "Rails way" of doing it? Specially the routing from Javascript to Rails controller and passing params to it is where I need your architectural input.
When you fetch your infos on the Client side with Javascript, I guess you initialize the variables provider_id, therapeutic_class, etc. Something like this:
var provider_id = $('#provider').val();
var thera_class = $('#therapeutic_class').val();
# etc.
# and then you do:
window.open("http://localhost:3000/pharmacy/patients?provider="+provider_id+"&"+"therapeutic_class="+thera_class+"&"+"medication_name="+medication_name);
If yes, I would suggest you to do so:
var url = "http://localhost:3000/pharmacy/patients?";
var params = { };
var params_names = [ 'provider', 'therapeutic_class', 'medication_name' ];
$.each(params_names, function(i, param_name) {
var value = $('#'+param_name).val();
if(value !== undefined && value != '') {
params[param_name] = value;
}
})
$.each(params, function(key, value) {
url += key + "=" + value + "&";
})
window.open(url)
I'm trying to make code from a Sinatra app work in the Rails context. The Sinatra app uses ajax requests to trigger the Sinatra routes/controller actions. For example, if you trigger the new function on a javascript model
new: function() {
var _this = this;
$.ajax({
url: "/gamestart",
type: "POST",
....
It will trigger the route/controller code in the Sinatra app
post "/new" do
end
When I tried to make this work in Rails, I'm getting a 500 internal server error. In my Rails app, the new_game button triggers an ajax request to a Rails route which triggers a controller action, and that controller action uses the Rails model to get data from the database. For some reason that doesn't seem like the right way to do it in Rails, and I'm wondering if it's the reason I'm getting the server error
GET http://localhost:3000/gamestart 500 (Internal Server Error)
If possible, can you tell me where in the chain of actions outlined below that error is arising and what I might do to fix it.
1 Click on the new game button triggers 'startNewGame' method
'click #new_game': 'startNewGame',
2 The startNewGame method calls method on Game model
startNewGame: function() {
this.model.new();
},
3 The new method in the Game model makes a GET request to the url '/gamestart'. I also tried a post request. I don't know why it would need to be a post request, but neither worked. (In the original Sinatra application, the gamestart url led immediately into the function post '/gamestart' do...)
new: function() {
var _this = this;
$.ajax({
url: "/gamestart",
type: "GET", \\\ also tried POST
success: function(response) {
var json = $.parseJSON(response);
_this.set({lost: false});
_this.set({win: false});
_this.trigger("gameStartedEvent", json);
}
})
},
4 I directed the url to a controller action in Rails router file
match 'gamestart' => 'locations#gamestart', :via => :get
Note, in the original Sinatra application, the route and the controller action were combined
5 The gamestart method of the locations_controller.rb
def gamestart
word = Word.get_random
masquerade_word = Word.masquerade(word)
session[:word] = word
session[:incorrect_guesses] = 0
session[:chars_left] = word.size
session[:revealed_word] = masquerade_word
{:word => masquerade_word}.to_json
end
6 The get_random method on the word model Word.rb, which is called from locations controller
def get_random
words = []
locations = Location.all (this pulls up the names of the locations from the db)
locations.each do |e|
words << e.name
end
words.sample
end
ERROR MESSAGE
GET http://localhost:3000/gamestart 500 (Internal Server Error) jquery.js:8215
XHR finished loading: "http://localhost:3000/gamestart". jquery.js:8215
send jquery.js:8215
jQuery.extend.ajax jquery.js:7767
window.Game.Backbone.Model.extend game.js:27
window.OptionsView.Backbone.View.extend.startNewGame optionsView.js:14
jQuery.event.dispatch jquery.js:3062
elemData.handle.eventHandle
Note, in the original Sinatra application, the route and the controller action were combined in the usual Sinatra way
post "/gamestart" do
word = Word.get_random
masquerade_word = Word.masquerade(word)
session[:word] = word
session[:incorrect_guesses] = 0
session[:chars_left] = word.size
session[:revealed_word] = masquerade_word
{:word => masquerade_word}.to_json
end
UPDATE
The 500 error seemed to be triggered by a missing template. This method in locations controller wasn't rendering anything. It didn't have a view file. I therefore changed the controller to make it respond_to :json and then use respond_with at the end of the action, but that triggered a 406 error.
def gamestart
word = Word.get_random
masquerade_word = Word.masquerade(word)
session[:word] = word
session[:incorrect_guesses] = 0
session[:chars_left] = word.size
session[:revealed_word] = masquerade_word
{:word => masquerade_word}.to_json
end
became now triggers 406 error
respond_to :json
def gamestart
word = Word.get_random
masquerade_word = Word.masquerade(word)
session[:word] = word
session[:incorrect_guesses] = 0
session[:chars_left] = word.size
session[:revealed_word] = masquerade_word
plainvariable = {:word => masquerade_word}.to_json ###changed
respond_with plainvariable ###changed
end
You say that your gamestart controller method is causing a server error due to a missing template. If we look at that controller method:
def gamestart
#...
{:word => masquerade_word}.to_json
end
we see that it returns a JSON string but it neglects to render anything. You don't call any rendering or redirection methods so Rails helpfully (ha ha) assumes that you want to render the gamestart view template; but, you have no such thing so you get an error.
You should render your JSON, not return it; something more like this:
def gamestart
#...
render :json => { :word => masquerade_word }
end