So I have a Rails API and an Ember application. At the moment, my Ember has a login.hbs template and a login.js controller.
I have done a ember install ember-ajax (https://github.com/ember-cli/ember-ajax).
On entering an email and password, I click on the login button which calls my login.js action loginClicked()
I have the following in my login controller:
// login.js controller
import Ember from 'ember';
export default Ember.Controller.extend({
email: '',
password: '',
actions: {
loginClicked() {
// alert("email: " + this.get('email') + "\npassword: " + this.get('password'));
let params = {
email: this.get('email'),
password: this.get('password')
};
post('/authenticate', {
params: params
});
}
}
});
In my login.js route handler, I have injected the ember-ajax service:
// login.js route handler
import Ember from 'ember';
export default Ember.Route.extend({
ajax: Ember.inject.service()
});
The problem is, my Mac terminal console is outputting an error saying:
controllers/login.js: line 16, col 7, 'post' is not defined.
I have also tried injecting the ember-ajax service into my controller but it made no difference.
Am I doing something wrong ?
Everything is described into the ember-ajax github page https://github.com/ember-cli/ember-ajax
export default Ember.Controller.extend({
ajax: Ember.inject.service(),
actions: {
loginClicked() {
let params = {
email: this.get('email'),
password: this.get('password')
};
return this.get('ajax').request('/authenticate', {
method: 'POST',
data: params
});
}
}
});
Basically, to access any property of your controller (component, ...) in ember, you need to get it using this.get('propertyName').
Here you need to use the request method of the ajax property (the injected service).
Related
Giving my first go at linking my React Native front end to my rails API back end. To do this I'm working with a user authentication flow and more specifically, signing in (creating the user on the database via User.create and a User model).
I've set up the Front end to work with Redux and send a fetch request, posting data from a form as JSON to rails. The data goes to Rails without any problem.
However, the problem seems to be coming from Rails, where I'm getting a 401 in the console 401 Unauthorized with the param going through Parameters: {"session"=>{}}. Why is this the case and how can I fix it? I've tried a bunch of solutions on SO, GitHub and some independent forms and nothing is working.
Essentially the action I want is for React to send the user data submitted in the username and password (seems all good there so far), Rails to process the username and password in the overridden sessions controller (it seems to be doing that) and to return a 'success' status and user authentication token which we can store in react native.
The SignInAction.js from React Native
export const emailChanged = (email) => {
return {
type: 'EMAIL_CHANGED',
payload: email
};
};
export const passwordChanged = (password) => {
return {
type: 'PASSWORD_CHANGED',
payload: password
};
};
export const loginUser = ({ email, password }) => {
return (dispatch) => {
dispatch({
type: 'LOAD_SPINNER'
});
fetch('http://localhost:3000/api/v1/auth/sign_in/', {
method: 'POST',
headers: {
//headers beyond log in user should contain the user authentication token to prove authentication
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
// user: {
email,
password,
// }
})
}).then((response) => {
console.log(response);
//this line is a problem
if (response.status === 401) {
console.log('AUTHENTICATION ERROR!!');
dispatch({
type: 'LOGIN_FAILED'
});
} else {
console.log('SUCCESS!!');
response.json().then(data => {
console.log(data);
dispatch({
type: 'LOGIN_USER_SUCCESS',
payload: data
});
});
}
});
};
};
The Routes.rb from Rails
Rails.application.routes.draw do
namespace :api do
scope :v1 do
mount_devise_token_auth_for 'User', at: 'auth', controllers: {
registrations: 'api/v1/overrides/registrations',
sessions: 'api/v1/overrides/sessions'
}
end
end
end
The /api/v1/overrides/sessions_controller.rb from Rails
module Api::V1::Overrides
class SessionsController < DeviseTokenAuth::SessionsController
# Prevent session parameter from being passed
# Unpermitted parameter: session
wrap_parameters format: []
end
end
Had the same problem, could never make it work with fetch, I assume there is some wrong header being sent impossible to track.
I switch to axios (yarn add axios) and then:
axios.post("http://localhost:3000/users/sign_in", {
user: {
email: "1#test.com",
password: "123123",
},
});
Problem solved
I'm trying to post a data(book) to my Rails Api using Vue JS and Axios. Here's the code from my BookList component:
<script>
import BookForm from './BookForm';
export default {
name: 'hello',
data(){
return{
books: []
}
},
mounted() {
axios.get("http://localhost:3000/api/v1/books")
.then(response => {this.books = response.data})
},
components:{
BookForm
},
methods:{
onClickForm(book){
console.log(book)
this.books.push(book)
axios.post("http://localhost:3000/api/v1/books",{book})
.then(function (response) {
console.log(response);
})
console.log('Book created')
}
}
}
</script>
I am able to post the book object but I get an error from the console. It seems my axios post request is not done correctly. Please note that I am sending the book object from my BookForm component emitting an event connected with the onClickForm method. What's wrong in my method? Thanks
This the error I am getting from the console:
This is the message that i get from the rails api server :
The book is created but I get a 500 internal error. Any help? Thanks
I'm using Ember for the front end and I am doing basic testing to see if I can properly render my data before adding components. I have two resources 'Topics' and 'Ratings' and I have added both a route and a model hook for these resources. When I type http://localhost:4200/topics, I am able to see all of the topics being rendered on the template. However, when I type http://localhost:4200/ratings, I receive an error on the console saying:
ember.debug.js:32096TypeError: Cannot read property 'some' of undefined
at error (route.js:21)
at Object.triggerEvent (ember.debug.js:28580)
at Object.trigger (ember.debug.js:53473)
at Object.Transition.trigger (ember.debug.js:53287)
at ember.debug.js:53107
at tryCatch (ember.debug.js:53806)
at invokeCallback (ember.debug.js:53821)
at publish (ember.debug.js:53789)
at publishRejection (ember.debug.js:53724)
at ember.debug.js:32054
Which is strange because in my rails console, I am receiving a HTTP: 200 response. Is there some error within the code of my routes? I made sure to mirror ratings similar to topics. Or is this an association issue? Both a USER and a TOPIC have many ratings. I provided snippets of my code below:
Application Route:
import Ember from 'ember';
export default Ember.Route.extend({
auth: Ember.inject.service(),
flashMessages: Ember.inject.service(),
actions: {
signOut () {
this.get('auth').signOut()
.then(() => this.transitionTo('sign-in'))
.then(() => {
this.get('flashMessages').warning('You have been signed out.');
})
.catch(() => {
this.get('flashMessages')
.danger('There was a problem. Are you sure you\'re signed-in?');
});
this.store.unloadAll();
},
error (reason) {
let unauthorized = reason.errors.some((error) =>
error.status === '401'
);
if (unauthorized) {
this.get('flashMessages')
.danger('You must be authenticated to access this page.');
this.transitionTo('/sign-in');
} else {
this.get('flashMessages')
.danger('There was a problem. Please try again.');
}
return false;
},
},
});
Rating Model:
import Model from 'ember-data/model';
import attr from 'ember-data/attr';
import { belongsTo } from 'ember-data/relationships';
export default Model.extend({
score: attr('number'),
user: belongsTo('user'),
topic: belongsTo('topic')
});
Rating Route:
import Ember from 'ember';
export default Ember.Route.extend({
model(params) {
return this.get('store').findRecord('rating', params.id);
},
});
```
Ratings Route:
import Ember from 'ember';
export default Ember.Route.extend({
model() {
return this.get('store').findAll('rating');
},
});
Router:
import Ember from 'ember';
import config from './config/environment';
const Router = Ember.Router.extend({
location: config.locationType,
});
Router.map(function () {
this.route('sign-up');
this.route('sign-in');
this.route('change-password');
this.route('users');
this.route('topics');
this.route('topic', { path: '/topics/:id'});
this.route('ratings');
this.route('rating', { path: '/ratings/:id'});
// Custom route in topics controller that will call NYT API or generate random-show
//topic. This is a GET request essentially
this.route('random-show');
});
export default Router;
SOLVED! Read the DOCS, and used EXPLICIT INVERSNESS:
https://guides.emberjs.com/v2.5.0/models/relationships/
Apparently, Ember needs help understanding when you have multiple has Many or Belong to for the same type.
This is how I do my routes in backbonejs where the routing and its params are obtained first before deciding which external template to call. I find this is quite flexible.
var Router = Backbone.Router.extend({
routes: {
//'': 'renderBasic',
':module/:method/': 'renderDynamicViewPageBasic',
':module/:branch/:method/': 'renderDynamicViewPageBranch',
':module/:branch/:method/set:setnumber/page:pagenumber/': 'renderDynamicViewPagePager',
':module/:branch/:method?set=:setnumber&page=:pagenumber': 'renderDynamicViewPagePager'
},
renderDynamicViewPageBasic: function (module,method) {
$(el).html(Handlebars.getTemplate('template1')(data));
},
renderDynamicViewPageBranch: function (module,branch,method) {
$(el).html(Handlebars.getTemplate('template2')(data));
},
renderDynamicViewPagePager: function (module,branch,method,setnumber,pagenumber) {
$(el).html(Handlebars.getTemplate('template3')(data));
}
});
How about in emberjs, can I do the same - do the rout and get its params afirst before deciding which external template to call?
I read the documentation and tested it. It seems to be less flexible - for instance,
App.Router.map(function() {
this.route("about", { path: "/about" });
this.route("favorites", { path: "/favs" });
});
Is it possible to get the route and params and then the controller before getting the template?
if not, it seems to be the same as case using Angularjs which I finally decided not to use it because it gets the template first before sorting out the params.
You can define the template "post params" in EmberJs using the renderTemplate hook, where you can customize which template you'd like to use.
http://emberjs.jsbin.com/oXUqUJAh/1/edit
App.Router.map(function() {
this.route('apple', {path: 'apple/:id'});
});
App.AppleRoute = Ember.Route.extend({
model: function(params) {
return {coolProperty: params.id};
},
renderTemplate: function(controller, model) {
// send in the template name
this.render(model.coolProperty);
}
});
You can pass a function together with $route params to get customized result in angularjs actually.
template: function($params) {
return app.$templateCache.get($params); // or make template yourself from another source
}
If I do a manual page refresh or set a redirect like this
}).then(function() {
document.location = "/";
}, function() {
in a function in my Ember app, an Ember controller property is becoming unset. I'm not sure if it matters which property is becoming unset, but in case it does, here's the code. In my application template, I check for whether a user is authenticated
{{#if isAuthenticated}}
blah blah
{{else}}
blah blah
{{/if}}
The property is set in the AuthController
App.AuthController = Ember.ObjectController.extend({
currentUser: null,
isAuthenticated: Em.computed.notEmpty("currentUser.email"),
login: function(route) {
var me;
me = this;
return $.ajax({
url: "/users/sign_in.json",
type: "POST",
data: {
"user[email]": route.currentModel.email,
"user[password]": route.currentModel.password
},
success: function(data) {
me.set('currentUser', data.user);
So, after I do a page refresh, my currentUser is (according to Ember) no longer showing as authenticated. However, on the (Ruby on Rails) server side the user is still authenticated. I put this code in the layout to check and after Ember thinks that I'm signed out (with a page refresh), my server code is still telling me I'm signed in (which in fact I am).
<% if current_user %>
there is a current user
<% end %>
Can you explain why this might be happening?
Your best is to set up is probably to make isAuthenticated a computed property that does an ajax GET to /users/current if currentUser is null. /users/current should return {} if the user is not authenticated, and the current user data if they are.
App.AuthController = Ember.ObjectController.extend({
currentUser: null,
isAuthenticated: function() {
var currentUser = this.get('currentUser');
if(Ember.isEmpty(currentUser)) {
$.ajax({
type: "GET",
url: "/users/current.json",
async: true
}).done( function( data ) {
me.set('currentUser', data.user);
});
return false;
} else {
return true;
}
}.property('currentUser'),
});
Why are you doing a manual page refresh? This way you are starting the browser completely from scratch and therefore the Ember App initializes again and therefore the property currentUser is not set on your Controller.
Instead of doing this:
}).then(function() {
document.location = "/";
}, function() {
I assume that you want to go to the start page of your app (since you want to go to "/"). Instead you should use the Ember feature of transitioning between routes. I do not know, where you execute the code above, but you can do this either from one of your controllers or in a route.
In a controller you could use transitionToRoute:
// index is a Route which is implicitly generated by Ember for you
this.transitionToRoute('index');
In a router you could use transitionTo:
this.transitionTo('index');