Hiyo
I'm pretty new to ember - working on building an Ember front, Rails back authentication with Devise. Trying to show server side errors on the Client...
I've read a bunch of stuff about this but nothing seems to work.
Login Page is at /sessions/new
Sessions New Template (Emblem.js)
Ember.TextField valueBinding="email" placeholder="Email" type="text"
= errors.email
Sessions New Route
SiloStore.SessionsNewRoute = Ember.Route.extend
model: -> #store.createRecord('session')
setupController: (controller, model) ->
controller.set('content', model)
Sessions New Controller
SiloStore.SessionsNewController = Ember.ObjectController.extend
needs: ['admin']
actions:{
logIn: ->
self = #
content = #content
#content.save().then(->
self.get('controllers.admin').set('content', content);
self.transitionToRoute 'admin.dashboard'
)
}
Sessions Controller (Rails)
render json: {
errors: {
email: ["invalid email or password"]
}
}, status: :unprocessable_entity
JSON Error from Rails Server in Console
{"errors":{"email":["invalidemailorpassword"]}}
Now instead of my Error showing under the Ember.TextField in my template - I'm getting a big ugly red error that looks like this:
POST http://dev.siloarts.net:3000/api/v1/sessions 422 (Unprocessable Entity)
Error: The backend rejected the commit because it was invalid: {email: invalid email or password}
Any Ideas?? I'm sure it's a dumb thing...
Oh oh oh and here is my debug info:
DEBUG: -------------------------------
DEBUG: Ember : 1.4.0-beta.1+canary.011b67b8
DEBUG: Ember Data : 1.0.0-beta.5+canary.d9ce2a53
DEBUG: Handlebars : 1.1.2
DEBUG: jQuery : 1.10.2
DEBUG: -------------------------------
THANKYOU IN ADVANCE LOVE HUGH
This error is also preventing errors structure binding. You can fix/patch it this way: call person.save().catch(->)always when you need to save. This will catch the error and do noting but one could still use becameError: and becameInvalidon the model or just implement the function on its own. You can also change your model class as follows:
App.Model = DS.Model.extend
save: (catchErr=true) ->
if catchErr
fail = ->
console.log('Save failed')
retutn #_super().catch(fail)
#_super()
Than change your base callas for a Person object
App.Person = App.Model.extend
...
And then when you need real catch use person.save(false).catch(fn)
I ran into the same error after upgrading. Downgrading to Ember 1.2.0 should solve your problem:)
Related
I'm learning rails and confused about some basics. Here is my API method:
def itunes_app_create
begin
app = Spaceship::Tunes::Application.create!(name: params[:itunes_app_name],
primary_language: "English",
version: params[:itunes_app_version],
sku: params[:itunes_app_sku],
bundle_id: params[:itunes_app_bundle_id],
team_id: params[:itunes_team_id])
render json: app.to_json, status: 200
rescue
render json: app.errors.full_messages.to_json, status: 200
end
end
My app.errors.full_messages.to_json line fails because well, I just made that up from something I saw. How do I return a message of what caused the method to fail?
Not sure if it matters, app is not part of my model. I just need to call this from my client app and then send back the result.
As a side question, what status should I return with the error in this case?
You should return the errors which occurred (if any) while creating the object. Your object is an instance of Spaceship::Tunes::Application, so you should be searching for whether this class defines any instance methods which return validation errors.
I am not familiar with this class, but after a quick look into it's documentation I do not see that it even has any validations in create method.
So you can just return a custom error message if by any chance the object creation failed.
As to
what status should I return with the error in this case?
Take a look into the list of status codes and pick suitable one (I think 400 (Bad Request) would do).
You could do something like this
def itunes_app_create
begin
app = Spaceship::Tunes::Application.create!(name: params[:itunes_app_name],
primary_language: "English",
version: params[:itunes_app_version],
sku: params[:itunes_app_sku],
bundle_id: params[:itunes_app_bundle_id],
team_id: params[:itunes_team_id])
render json: app.to_json, status: 200
rescue => e
render json: {error: e, status: 500}.to_json
end
end
But if you are building out a full api you might want to come up with your own error codes and a convention on when you will use which of the http errors codes that Andrey so politely included. Also its not a good practice to just blindly catch all error types because it is behavior concealing and it will generalize the behavior of your app in difference scenarios. In my example since you are return the error message it give you a little bit a visibility.
any time you are urged to write something like this
rescue => e
write something like this instead
rescue SyntaxError => e
Be very deliberate with your error handling, see this question for why
I'm using a stack consisting of Rails with Grape (for API stuff) and Devise (for user stuff), and Ember with Ember CLI and Ember Simple Auth. I want to implement authorization using the DeviseAuthenticator exposed by Simple Auth. My login controller looks like this:
// app/controllers/login.js
import Ember from 'ember'
export default Ember.Controller.extend({
session: Ember.inject.service('session'),
actions: {
authenticate () {
let {identification, password} = this.getProperties('identification', 'password')
this.get('session').authenticate('authenticator:devise', identification, password).catch(reason => {
console.log(reason.error || reason)
})
}
}
})
and my Devise authenticator setup:
// app/authenticators/devise.js
import Devise from 'ember-simple-auth/authenticators/devise'
export default Devise.extend({
serverTokenEndpoint: 'http://localhost:4200/api/v1/users/sign_in',
resourceName: 'user',
crossOriginWhiteList: ['http://localhost:4200/']
})
For development purposes, I've commented out the error! "401 Unauthorized", 401 unless authenticated part in my Grape config (that's another problem though) just to see if it even works, but it throws this:
POST http://localhost:4200/api/v1/users/sign_in 405 (Method Not Allowed)
I have no idea what to do, and as such would appreciate some help. If I can post more code from other files, I'd be happy to, just tell me.
Found out that my devise routes are at /users/sign_in, not at /api/v1/users/sign_in.
The following code works fine when deployed locally in a dev environment from a controller (using run-app). It's used to create a JavaScript object with all messages in the current language.
class LocaleController {
private Map<String, String> getMessages() {
// This is the line in question, the rest is just context
def bundle = ResourceBundle.getBundle("grails-app/i18n/messages");
def map = [:]
bundle.keys.each { msg ->
map[msg] = message(code: msg)
}
return map
}
def index() {
header("Cache-Control", "public, max-age=31536000")
render(view: "index", model: [messages: getMessages()], contentType: "text/javascript")
}
}
However, when this is run from a deployed server, I get the following error message
errors.GrailsExceptionResolver - MissingResourceException occurred when processing request: [GET] /compose/locale/index
Can't find bundle for base name grails-app/i18n/messages, locale en_US. Stacktrace follows:
java.util.MissingResourceException: Can't find bundle for base name grails-app/i18n/messages, locale en_US
at java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.java:1499)
at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1322)
at java.util.ResourceBundle.getBundle(ResourceBundle.java:1028)
at com.accelrys.compose.app.LocaleController.getMessages(LocaleController.groovy:13)
at com.accelrys.compose.app.LocaleController.index(LocaleController.groovy...
I would have preferred not to read the file directly, so I tried http://mrhaki.blogspot.com/2011/11/grails-goodness-internationalize.html which uses http://grails.org/plugin/jawr but that page has been offline for the past 10 days.
I also tried following the steps in How can I create a map with all i18n-messages in Grails but it wouldn't use my customized message source, I copied the answer verbatim (clean/comile/run-app) but it was still using PluginAwareResourceBundleMessageSource instead of ExtendedPluginAwareResourceBundleMessageSource
2014-09-29 17:15:33,447 [http-bio-8080-exec-2] ERROR errors.GrailsExceptionResolver - MissingMethodException occurred when processing request: [GET] /compose/locale/index - parameters: jklgfdgdfg:
No signature of method: org.codehaus.groovy.grails.context.support.PluginAwareResourceBundleMessageSource.getMessageCodes() is applicable for argument types: () values: []. Stacktrace follows:
Message: No signature of method: org.codehaus.groovy.grails.context.support.PluginAwareResourceBundleMessageSource.getMessageCodes() is applicable for argument types: () values: []
Line | Method
->> 15 | getMessages in com.accelrys.compose.app.LocaleController$$EOrHmJbB
Any suggestions on what else I can try?
It turns out that How can I create a map with all i18n-messages in Grails does work correctly.
I am not sure why it wasn't working, as one can see from the error message in the question. Maybe it had something to do with the following error at startup.
java.lang.RuntimeException: Reloading agent exited via exception, please raise a jira
Error |
at org.springsource.loaded.agent.ClassPreProcessorAgentAdapter.transform( ClassPreProcessorAgentAdapter.java:104)
Error |
In any case, if you try this and it doesn't work at first, don't give up. Try again later.
Update
It turns out that the reason the plugin didn't work was because grails install-plugin is deprecated, adding compile ":jawr:3.5.1" to the plugins section of BuildConfig.groovy made it work.
I've got a AngularJS/Rails app and I want to test my AngularJS controller is posting to the backend server when creating a new record. (I'm using jasmine for my tests)
Here is my attempted test
describe "create", ->
beforeEach(inject ( ($controller, $rootScope, $location, $state, $httpBackend) ->
#redirect = spyOn($location, 'path')
#httpBackend.whenGET('/assets/layouts/default.html.erb').respond(200)
#httpBackend.whenGET('/assets/letters/index.html.erb').respond(200)
#httpBackend.whenPOST('/api/letters').respond(200)
$controller("LettersController", { $scope: #scope, $location: #location })
))
it "sends a post to the backend", ->
#httpBackend.expectPOST('/api/letters', {"letter":{},"_utf8":"☃"}).respond(200)
#scope.create()
Here s the code which I'm testing:
$scope.create = ->
Letter.save(
{}
,
letter:
subject: $scope.letter.subject
body: $scope.letter.body
# success
, (response) ->
$location.path "/letters"
# failure
, (response) ->
)
The code in question works correctly and the test passes. The problem is if I comment my Letter.save code out (which makes the post through AngularJS resources) then my test still passes.
How can I get my test to work properly?
My full test application is here: https://github.com/map7/angularjs_rails_example2
You need to verify that there are no outstanding requests at the end of your tests:
$httpBackend.verifyNoOutstandingRequest();
You also need to verify that there are no outstanding expectations with $httpBackend.verifyNoOutstandingExpectation
This should prevent you from getting false positives I believe.
Also, I'm not sure that your expectPOST should return true because you don't seem to be sending "_utf8":"☃", however I haven't looked at the full source code so I could be missing something.
I would try to trim down the example so that your create method calls a route and you expect that route to be called and work from there. You might try removing the whenPOST and replace the expectPOST with #httpBackend.expectPOST('/api/letters').respond(200)
I've got a Backbone.js/Rails app and I'm trying to create a new object through Backbone model.save().
The server is returning a 302 moved, but checking the rails controller, the create object exists, and I can navigate to the index, so the routes are properly in place.
I've tried replacing the backbone.js with a regular jquery .ajax function, and both return the 302, as I originally thought the error was in backbone, but I think this is showing that the error is actually in rails.
The request payload/parameters is pretty simple
{"user_id":130,"message_text":"does this go 302","authenticity_token":"GxN8nPf5YwS2j2HhWZxWiKej3Y72Vb5IQZ98u5Nl2gs="}
The backbone save method is
var user_message = new Myapp.Models.UserMessage({
user_id: user.id,
message_text: $('input[name="message"]',this.el).val()
});
user_message.save({
success: function(response) {
new Message({message: response.message});
},
error: function() {
new Error({ message: "adding message" });
}
});
A "302" response has nothing to do with backbone, as you've noted. It looks like you have authorization / authentication code that is causing this.