I have to upgrade an application previously developed by other guys with Symphony 1.4.
Inside my action.class.php there are two different functions:
public function executeCreateTask(sfWebRequest $request) {...}
public function executeCreateEvent(sfWebRequest $request) {...}
and inside my routing.yml I have 2 routes:
evaluation_task_create:
url: /evaluation/:id/task/create
class: sfDoctrineRoute
options: { model: Evaluation, type: object }
param: { module: evaluation, action: createTask, sf_format: html }
requirements: { sf_method: post }
and
evaluation_event_create:
url: /evaluation/:evaluation_id/event/create
class: sfDoctrineRoute
options: { model: CustomEvent, type: object }
param: { module: evaluation, action: createEvent, sf_format: html }
requirements: { sf_method: post }
The url
http://www.mysite/evaluation/21/task/create works perfectly (Creates a new task)
The url
http://www.mysite/evaluation/21/event/create returns an 404 error.
Any idea why I have this routing issue?
You need to be able to debug further, since you are not getting an sfError404Exception. Have you set debug to true in your ApplicationConfiguration? You can do this in your webdispatcher for your dev environment.
$configuration = ProjectConfiguration::getApplicationConfiguration(
'backend',
'dev',
true
);
And in your application's settings.yml:
dev:
error_reporting: <?php echo (E_ALL | E_STRICT)."\n" ?>
web_debug: true
And in your application's factories.yml make sure you have set
dev:
logger:
param:
loggers:
sf_web_debug:
param:
xdebug_logging: true
In the createEvent action of your evaluation module, you have probably something like
$this->evalution = $this->getRoute()->getObject();
To get the right object from the route, you need to use :id variable for the id of the object and specify the right model Evaluation and not CustomEvent. So try to change evaluation_event_create route to:
evaluation_event_create:
url: /evaluation/:id/event/create
class: sfDoctrineRoute
options: { model: Evaluation, type: object }
param: { module: evaluation, action: createEvent, sf_format: html }
requirements: { sf_method: post }
and clear your cache.
Related
I'm working on a project that uses Rails and React, with react-router version 4.2.0 and react-router-redux 5.0.0-alpha.9. It's the first time I use React and I'm having trouble routing.
In my routes.jsx file I have the following path:
const routes = [
{ path: /\/events\/(\d)$/, action: () => <EventForm /> },
];
When I type http://localhost:3000/events/2 in my browser I get the content back.
I want to modify my route so this link won't be valid unless there's a userToken appended to it as a query string. (I know this is not the best security practice but it's valid for the purpose of this project)
For example, the following link http://localhost:3000/events/2 should not work, but the link http://localhost:3000/events/2?userToken=abc should work.
I tried these options but it didn't work:
{ path: /\/events\/(\d)\?userToken\=(\w)$/, action: () => <EventForm /> }
{ path: /\/events\/(\d)\?userToken=[\w]$/, action: () => <EventForm /> }
Thanks!
One way is to check url param in componentDidMount lifecycle method of EventForm:
class EventForm extends Component{
componentDidMount(){
const {location, history} = this.props // these are by design in props when using react-router
if(!location.query.userToken){
history.push('/login') // or whatever route
}
}
render(){
return (<div>...</div>)
}
}
export default EventForm
In a Rails 5.1 app (without jQuery) how can I pass nested params via a GET ajax request?
I have the following
Rails.ajax({
url: select.getAttribute('data-url') + "?xxx",
type: "GET"
});
If I replace xxx with, for instance, pippo=pluto, in my controller
params[:name] #=> "pluto"
However, in my controller, I need to be able to access a nested param as below.
params[:user][:name] #=> "pluto"
It seems a simple problem but I cannot find a solution.
Here my JS
document.addEventListener('turbolinks:load', function() {
var select = document.querySelector("select[name='user[name]']")
if(select.options[select.selectedIndex].value) {
Rails.ajax({
url: select.getAttribute('data-url'),
type: "GET",
data: {
user: {
name: select.options[select.selectedIndex].value
}
}
});
}
});
Which produces (user[:name] is always selected)
{"object Object"=>nil, "controller"=>"steps", "action"=>"index"} permitted: false>
The query string works fine (but is ugly)
Rails.ajax({
url: select.getAttribute('data-url') + '?user[name]=' + select.options[select.selectedIndex].value,
type: "GET"
});
SIDE QUESTION: To avoid the ajax request in the first place is there an alternative way to automatically trigger the request of the select below when the page is loaded? Currently, it is triggered only when the selected option changes
<%= f.select :user, MyUsers.all,
{ data: { remote: true, url: duplicate_users_path } } %>
use data option in ajax (recommended)
Rails.ajax({
url: select.getAttribute('data-url'),
type: 'GET',
data: {
users: {
pippo: 'pluto',
pippo2: 'pluto2'
}
}
});
or query string as array
Rails.ajax({
url: select.getAttribute('data-url') + '?users[pippo]=pluto&users[pippo2]=pluto2',
type: 'GET'
});
I want to define a remote method with the following path:
http://localhost:3000/api/dataSourceTestings/{id}/a
In the dataSourceTesting.json file I defined its path as :
"http": [
{
"path": "/{id}/a",
"verb": "put"
},
]
But when I send request on this end point it gives me the error that can't found the method for this endpoint.
Do I need to define a relationship for it or is there any other way to define a remote method for this path?
you should define your remotemethod in dataSourceTesting.js file:
DataSourceTesting.remoteMethod('putDataSourceTestings', {
accepts: [
{arg: 'id', type: 'string'}],
http: {path:'/:id/a', verb:'put'},
returns: {arg: 'result', type: 'json'}
});
then implement your putDataSourceTestings function:
DataSourceTesting.putDataSourceTestings = function(id, cb){
//your logic goes here
}
A blog related to this issue:
https://strongloop.com/strongblog/remote-methods-in-loopback-creating-custom-endpoints/
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
}
I've got an angularjs app embedded in a rails app. I'm using the RESTful methods provided by rails for a resource named "Task." Here are the routes I'm dealing with:
GET /api/v1/tasks.json
POST /api/v1/tasks.json
GET /api/v1/tasks/:id.json
PUT /api/v1/tasks/:id.json
DELETE /api/v1/tasks/:id.json
I've got an angularjs-resource for the Task item where the GET for all of the tasks works fine. (Code is in coffee script)
App.factory "Task", ["$resource", "$cookies", ($resource, $cookies) ->
$resource "/api/v1/tasks:slash:type.json?api_token=:api_token",
api_token: $cookies.api_token
type: '#id'
,
all:
method: "GET"
isArray: true
create:
method: "POST"
update:
method: "PUT"
params:
slash: "/"
remove:
method: "DELETE"
]
As you can sort of see here, I'm trying to insert a slash for the PUT method to get the format /api/v1/tasks/:id.json. Unfortunately, angular puts this in as a %2f rather than a slash. I'm not particularly excited about the quality of this code, since added the slash parameter makes it less readable.
Here's my angularjs controller using this resource:
taskController = App.controller 'TasksController', ($rootScope, $scope, $http, $cookies, Task) ->
$scope.message = $cookies.api_token
$scope.tasks = Task.all()
$scope.selectedTask = null
$scope.editTask = (task) ->
$scope.selectedTask = task
$scope.editDescription = task.description
$rootScope.date = new Date(task.dueDate)
console.log($rootScope.dt)
$scope.taskModal = true
$scope.saveTask = ->
$scope.taskModal = false
$scope.selectedTask.$update()
# Task.update({taskID: $scope.selectedTask.id, task: $scope.selectedTask})
console.log 'Implement saving...'
$scope.tasks = Task.all()
$scope.cancelTask = ->
$scope.taskModal = false
$scope.taskModalOptions = {
dialogFade: true
}
taskController.$inject = ['$rootScope', '$scope', '$http', '$cookies', 'Task']
Basically, my question is does anyone have an example of how do reproduce the traditional rails/RESTful URL formats with an angularjs resource? I've looked at several StackOverflow questions and can't seem to find a good answer. Any help is appreciated.
Have a look at restangular, its specifically designed to make HTTP verb requests to any REST api simple & easy.
https://github.com/mgonto/restangular
I had the problem with this and the nesting of the JSON data. The following code seems to work for me:
contacts.factory('Contacts', ['$resource',
function($resource) {
function nestData(data, headersGetter) {
return JSON.stringify({
contact: data
});
};
return $resource('/api/v1/contacts/:id.json', {
id: '#id'
}, {
'index': {
method: 'GET',
isArray: true
},
'show': {
method: 'GET',
isArray: false
},
'create': {
method: 'POST',
transformRequest: nestData
},
'save': {
method: 'PUT',
transformRequest: nestData
},
'destroy': {
method: 'DELETE'
}
}); // Note the full endpoint address
}
]);
In my controller I'm able to use:
function createContact(data) {
Contacts.save({
name: data.name,
phone: data.phone
});
}
Please give it a try and let me know