rails:使用json和用户身份验证创建新对象

时间:2013-06-24 00:22:25

标签: ruby-on-rails json

我想通过JSON POST在rails服务器上创建一个'image'对象。这工作得很好,但现在我添加了用户身份验证,它不再起作用了。 我使用gem'depaise'进行身份验证。 注册,登录和注销与json完美配合。

user.rb:

class User < ActiveRecord::Base
  has_many :images

  attr_accessible :name, :email, :password, :password_confirmation, :remember_me, :encrypted_password

  has_secure_password

  validates :email, format: /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, uniqueness: true

end

images_controller:

class ImagesController < ApplicationController

before_filter :require_login #checks if user is logged in before user accesses images

  respond_to :json

def index
    @images = current_user.images

    respond_to do |format|
      format.html { }
      format.json { render :json => {:success => true,
                      :info => "images",
                      :data => @images } }
    end

  end

  def edit
    @image = current_user.images.find(params[:id])
  end

  def new
    @image = current_user.images.build
  end


  def create
    @image = current_user.images.build(params[:image])

    respond_to do |format|
      if @image.save
        format.html { redirect_to images_path }
        format.json { render :json => @image }
      else
        format.html { render "new" }
        format.json { render json: @image.errors, status: :unprocessable_entity }
      end
    end #respond_to
  end

private

  def require_login
    unless user_signed_in? #in application_controller
      redirect_to login_path,
      alert: "Login first."
    end
  end

  end

sessions_controller:

class SessionsController < ApplicationController

  respond_to :json

  def new
    #empty because no underlying model
  end


  def create
    #user = User.find_by_email(params[:user][:email]) #when JSON: { "user" : { "email":"asdf@asdf.at", "password":"asdf" }}
    user = User.find_by_email(params[:email]) #when JSON: { "email":"asdf@asdf.at", "password":"asdf" }

    respond_to do |format|
      if user && user.authenticate(params[:password]) #because user has_secure_password
        session[:user_id] = user.id

        format.html { redirect_to images_path, notice: "Login successful!" }
        format.json { render :json => {:success => true,
                      :info => "Logged in",
                      :data => { } } }
      else
        format.html { flash.now.alert = "Wrong email or password"
                    render "new" }
        format.json { render :json => {:success => false, :info => "Wrong email or password" } }
      end
    end
  end



  def destroy

    session[:user_id] = nil
    respond_to do |format|
      format.html { redirect_to root_path, notice: "Logout successful!" }
      format.json { render :json => {:success => true,
                      :info => "Logged out",
                      :data => { } } }
    end

  end


end

rake routes:

      root        /                          pages#home
 new_image GET    /images/new(.:format)      images#new
    images GET    /images(.:format)          images#index
     image GET    /images/:id(.:format)      images#show
           POST   /images(.:format)          images#create
edit_image GET    /images/:id/edit(.:format) images#edit
           PUT    /images/:id(.:format)      images#update
     image DELETE /images/:id(.:format)      images#destroy
     users POST   /users(.:format)           users#create
  new_user GET    /users/new(.:format)       users#new
     login GET    /login(.:format)           sessions#new
  sessions POST   /sessions(.:format)        sessions#create
    logout DELETE /logout(.:format)          sessions#destroy

application_controller:

class ApplicationController < ActionController::Base
  protect_from_forgery

  def current_user
    if session[:user_id]
      @current_user ||= User.find(session[:user_id])
    end
  end

  def user_signed_in?
    current_user.present?
  end

  helper_method :user_signed_in?

end

登录后,有效(显示图像也适用于GET method and url http://localhost:3000/images),我无法使用JSON创建新图像。这是我的客户请求(我使用Chrome的简单REST客户端):

url:           http://localhost:3000/images
method:        POST
Content-Type:  application/json
               Accept: application/json
Data:          {"image":{ "title":"someTitle","url": "someUrl" }}

响应:

500 Internal Server Error
<h1>Template is missing</h1>
<p>Missing template sessions/new, application/new with {:locale=&gt;[:en], :formats=&gt;[:json], :handlers=&gt;[:erb, :builder, :coffee]}. Searched in:
  * &quot;c:/Users/XXX/workspaceRubyOnRails/my_server/app/views&quot;
  * &quot;c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/devise-2.2.4/app/views&quot;
</p>

2 个答案:

答案 0 :(得分:1)

似乎您的JSON请求未经过身份验证。因此,Devise会将您发送到登录页面。但是您没有登录页面的JSON版本,因此会出现Missing template sessions/new错误。

您可以将Cookie与请求一起发送,甚至更好,使用Devise中的token authentication,这样您就可以使用令牌进行身份验证,请执行以下操作:

curl -v -H "Accept: application/json" -H "Content-type: application/json" http://localhost:3000/images?auth_token=<token>

您可以在此处找到一些代码示例:https://github.com/plataformatec/devise/wiki/How-To:-Simple-Token-Authentication-Example

答案 1 :(得分:0)

我认为您需要通过Chrome简单REST客户端进行身份验证 - 您的rails应用程序似乎区分了Chrome本身和其他客户端。

一旦你克服了这个障碍,我会扩大这个答案。