在Rails项目中找不到AngularJS工厂方法

时间:2015-02-14 10:03:59

标签: angularjs ruby-on-rails-4

我目前正在研究这个AngularJS教程:学习使用Angular和Rails https://thinkster.io/angular-rails/构建现代Web应用程序,我认为这是一个很好的资源,展示了如何使用AngularJS构建Rails Web应用程序。

到目前为止,我已经成功完成了超过三分之二的教程,但现在我面临着工厂服务的一些问题。当我点击帖子按钮创建新帖子时,我收到以下错误:

enter image description here

错误消息

angular.js?body=1:11608 TypeError: undefined is not a function
    at Scope.$scope.addPost (http://0.0.0.0:3000/assets/home/mainCtrl.js?body=1:23:24)

它指向 mainCtrl.js 文件中的以下代码:

                posts.create({
                    title: $scope.title,
                    link: $scope.link,
                });

整个 mainCtrl.js 文件:

angular.module('flapperNews')
.controller('MainCtrl', ['$scope', 'posts', function ($scope, posts) {

        $scope.test = 'Hello world!';

        $scope.posts = posts.posts;

        $scope.posts.push({
            title: $scope.title,
            link: $scope.link,
            upvotes: 0,
            comments: [
              { author: 'Joe', body: 'Cool post!', upvotes: 0 },
              { author: 'Bob', body: 'Great idea but everything is wrong!', upvotes: 0 }
            ]
        });

        $scope.addPost = function () {

            if (!$scope.title || $scope.title === '') { return; }
                 posts.create({
                    title: $scope.title,
                    link: $scope.link,
                });
            $scope.title = '';
            $scope.link = '';
        };

        $scope.incrementUpvotes = function(post) {
            posts.upvote(post);
        };
}]);

在上面的控制器中,如果在引入工厂创建方法之前将addPost函数替换为教程中使用的函数,那么它可以正常工作。

工作代码:

$scope.addPost = function(){
  if(!$scope.title || $scope.title === '') { return; }
  $scope.posts.push({
    title: $scope.title,
    link: $scope.link,
    upvotes: 0
  });
  $scope.title = '';
  $scope.link = '';
};

所以不知何故工厂的posts.create方法引起了问题(尽管posts.posts是可访问的)。

以下是 post.js 文件o.create方法导致当前问题

angular.module('flapperNews').factory('posts', ['$http',
    function($http){

        var o = {
            posts: []
        };
        return o; 

        o.getAll = function() {
            return $http.get('/posts.json').success(function(data){
                angular.copy(data, o.posts);
            });
        };

        o.create = function(post) {
            console.log("o.create");
            return $http.post('/posts.json', post).success(function(data){
                o.posts.push(data);
            });
        };

        o.upvote = function(post) {
          return $http.put('/posts/' + post.id + '/upvote.json')
            .success(function(data){
              post.upvotes += 1;
            });
        };

        resolve: {
            postPromise: ['posts', function(posts){
                return posts.getAll();
            }]
        }

    }
]);

app.js 文件

angular.module('flapperNews', ['ui.router', 'templates'])
.config([
  '$stateProvider',
  '$urlRouterProvider',
  function($stateProvider, $urlRouterProvider) {
    $stateProvider
      .state('home', {
        url: '/home',
        templateUrl: 'home/_home.html',
        controller: 'MainCtrl'
      })
      .state('posts', {
        url: '/posts/{id}',
        templateUrl: 'posts/_posts.html',
        controller: 'PostsCtrl'
      })
    $urlRouterProvider.otherwise('home')
}]);

如果有人知道这里的根本问题,请提供建议。非常感谢: - )

我的rails版本4.0.2,我正在使用Linux Ubuntu 12.04

有些想法,如果我不能让工厂方法有效,那么我可能会将这些方法直接放在控制器中解决问题,希望如下:-)

2 个答案:

答案 0 :(得分:1)

你过早地返回了这个对象,其他函数没有注册(因为它们是函数表达式,而不是函数声明,它们没有得到hoisted)。将return o;移到最后,它会起作用:

app.factory('posts', ['$http',
    function($http){

        var o = {
            posts: []
        };


        o.getAll = function() {
            return $http.get('/posts.json').success(function(data){
                angular.copy(data, o.posts);
            });
        };

        o.create = function(post) {
            alert('In create!');
            console.log("o.create");
            return $http.post('/posts.json', post).success(function(data){
                o.posts.push(data);
            });
        };

        o.upvote = function(post) {
          return $http.put('/posts/' + post.id + '/upvote.json')
            .success(function(data){
              post.upvotes += 1;
            });
        };

        resolve: {
            postPromise: ['posts', function(posts){
                return posts.getAll();
            }]
        }
        return o;

    }
])

请参见此工作Fiddle

答案 1 :(得分:1)

您的解决方案声明应该在您的app.js中处于主页状态正如教程所说,&#34;通过这种方式使用resolve属性,我们确保无论何时进入我们的home状态,我们都会在状态实际完成加载之前自动查询后端的所有帖子。&#34; < / p>

App.js:

angular.module('flapperNews', ['ui.router', 'templates'])

.config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {

  $stateProvider
  .state('home', {
      url: '/home',
      templateUrl: 'home/_home.html',
      controller: 'MainCtrl',
      resolve: {
        postPromise: ['posts', function(posts){
          return posts.getAll();
        }]
      }
    })

  .state('posts', {
      url: '/posts/{id}',
      templateUrl: 'posts/_posts.html',
      controller: 'PostsCtrl'
 })

   $urlRouterProvider.otherwise('home');
}]);