Ruby on rails Rails中的RESTAPI帮助

Ruby on rails Rails中的RESTAPI帮助,ruby-on-rails,api,rest,Ruby On Rails,Api,Rest,我正试图通过GEM使用我们的会计软件包(FreeAgentCentral)和他们的API发布一些信息 http://github.com/aaronrussell/freeagent_api/ 我有以下代码来让它工作(假设): Kase控制器 def create @kase = Kase.new(params[:kase]) @company = Company.find(params[:kase][:company_id]) @kase = @company.kas

我正试图通过GEM使用我们的会计软件包(FreeAgentCentral)和他们的API发布一些信息

http://github.com/aaronrussell/freeagent_api/
我有以下代码来让它工作(假设):

Kase控制器

def create
    @kase = Kase.new(params[:kase])
    @company = Company.find(params[:kase][:company_id])
    @kase = @company.kases.create!(params[:kase])

    respond_to do |format|
      if @kase.save
        UserMailer.deliver_makeakase("dropbox@12808311.macandco.highrisehq.com", "Highrise", @kase)
        @kase.create_freeagent_project(current_user)

        #flash[:notice] = 'Case was successfully created.'
        flash[:notice] = fading_flash_message("Case was successfully created & sent to Highrise.", 5)

        format.html { redirect_to(@kase) }
        format.xml  { render :xml => @kase, :status => :created, :location => @kase }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @kase.errors, :status => :unprocessable_entity }
      end
    end
  end
为了节省您的时间,重要的部分是:

@kase.create_freeagent_project(current_user)
Kase型号

 # FreeAgent API Project Create
  # Required attribues
  #   :contact_id
  #   :name
  #   :payment_term_in_days
  #   :billing_basis                    # must be 1, 7, 7.5, or 8
  #   :budget_units                     # must be Hours, Days, or Monetary
  #   :status                           # must be Active or Completed
  def create_freeagent_project(current_user)
    p = Freeagent::Project.create(
      :contact_id             => 0,
      :name                   => "#{jobno} - #{highrisesubject}",
      :payment_terms_in_days  => 5,
      :billing_basis          => 1,
      :budget_units           => 'Hours',
      :status                 => 'Active'
    )
   user = Freeagent::User.find_by_email(current_user.email)
    Freeagent::Timeslip.create(
      :project_id => p.id,
      :user_id => user.id,
      :hours => 1,
      :new_task => 'Setup',
      :dated_on => Time.now
    )
  end
lib/freeagent\u api.rb

require 'rubygems'
gem 'activeresource', '< 3.0.0.beta1'
require 'active_resource'

module Freeagent

  class << self
    def authenticate(options)
      Base.authenticate(options)
    end
  end

  class Error < StandardError; end

  class Base < ActiveResource::Base
    def self.authenticate(options)
      self.site = "https://#{options[:domain]}"
      self.user = options[:username]
      self.password = options[:password]
    end
  end

  # Company

  class Company
    def self.invoice_timeline
      InvoiceTimeline.find :all, :from => '/company/invoice_timeline.xml'
    end
    def self.tax_timeline
      TaxTimeline.find :all, :from => '/company/tax_timeline.xml'
    end
  end
  class InvoiceTimeline < Base
    self.prefix = '/company/'
  end
  class TaxTimeline < Base
    self.prefix = '/company/'
  end

  # Contacts

  class Contact < Base
  end

  # Projects

  class Project < Base

    def invoices
      Invoice.find :all, :from => "/projects/#{id}/invoices.xml"
    end

    def timeslips
      Timeslip.find :all, :from => "/projects/#{id}/timeslips.xml"
    end

  end

  # Tasks - Complete

  class Task < Base
    self.prefix = '/projects/:project_id/'        
  end

  # Invoices - Complete

  class Invoice < Base

    def mark_as_draft
      connection.put("/invoices/#{id}/mark_as_draft.xml", encode, self.class.headers).tap do |response|
        load_attributes_from_response(response)
      end
    end
    def mark_as_sent
      connection.put("/invoices/#{id}/mark_as_sent.xml", encode, self.class.headers).tap do |response|
        load_attributes_from_response(response)
      end
    end
    def mark_as_cancelled
      connection.put("/invoices/#{id}/mark_as_cancelled.xml", encode, self.class.headers).tap do |response|
        load_attributes_from_response(response)
      end
    end

  end

  # Invoice items - Complete

  class InvoiceItem < Base
    self.prefix = '/invoices/:invoice_id/'
  end

  # Timeslips

  class Timeslip < Base

    def self.find(*arguments)
      scope   = arguments.slice!(0)
      options = arguments.slice!(0) || {}
      if options[:params] && options[:params][:from] && options[:params][:to]
        options[:params][:view] = options[:params][:from]+'_'+options[:params][:to]
        options[:params].delete(:from)
        options[:params].delete(:to)
      end

      case scope
        when :all   then find_every(options)
        when :first then find_every(options).first
        when :last  then find_every(options).last
        when :one   then find_one(options)
        else             find_single(scope, options)
      end
    end    
  end

  # Users

  class User < Base
    self.prefix = '/company/'
    def self.find_by_email(email)
      users = User.find :all
      users.each do |u|
        u.email == email ? (return u) : next
      end
      raise Error, "No user matches that email!"
    end
  end

end
Freeagent.authenticate({
   :domain => 'XXXXX.freeagentcentral.com',
   :username => 'XXXX@XXXXXXX.co.uk',
   :password => 'XXXXXX'
   })
在尝试创建新案例并将详细信息发送给FreeAgent时,上述操作会导致以下错误:

ActiveResource::ResourceNotFound in KasesController#create

Failed with 404 Not Found

如果有人能解释这个问题,我们将不胜感激

谢谢


丹尼

你怎么称呼他?对于普通的restful创建操作,它可能是来自表单或其他内容的POST,但404通常是从失败的GET操作中呈现的,其中ActiveRecord find无法找到具有特定id的记录。我的最佳猜测是,您正在使用GET调用create,并且

user = Freeagent::User.find_by_email(current_user.email)
根本无法找到带有该电子邮件的用户,因此引发ResourceNotFound异常

此外,这段代码让我感到困惑:

 @kase = Kase.new(params[:kase])
 @company = Company.find(params[:kase][:company_id])
 @kase = @company.kases.create!(params[:kase])

 respond_to do |format|
   if @kase.save
你为什么在这里两次创建@kase,一次是用kase.new,一次是用kase.create?另外,请注意该行:

if @kase.save
@company.kases.create!(params[:kase])
将始终计算为true,因为行:

if @kase.save
@company.kases.create!(params[:kase])
如果它为false,则会引发异常,这是另一种说法@kase.save是多余的,因为create!已经保持了Kase的新记录了

编辑:我认为你的意思是:

# this line can go @kase = Kase.new(params[:kase]) 
@company = Company.find(params[:kase][:company_id])
@kase = @company.kases.build(params[:kase])
编辑:您可能需要这样的新操作:

def new
  @kase = Kase.new # no params here
end
“新”erb模板将有一个表单_,用于以下内容:

<% form_for @kase do |k| %>


默认情况下,该表单将把表单中的参数发布到create操作,假设您在路由中设置了类似resources:kase的内容。这应该让你开始。像你正在做的那样遵循标准教程,事情应该会变得更简单

我已双重/三重检查当前用户的电子邮件地址是否与freeagent的电子邮件地址匹配。ResourceNotFound异常是否还有其他原因?我需要看看你关于kase create的第二条评论,我认为你是对的!谢谢,丹尼,这是我能看到的唯一一条可能找不到的线。可能是某些空格符导致查找失败?在find_by_电子邮件之后添加一些输出,以确保您找到了用户。然后查看要验证的服务器输出。此外,使用GET创建新资源被认为是错误的restful形式。你可以考虑把它改为POST。GET不仅使意外创建新记录变得容易,而且404在创建新记录的上下文中没有意义。我目前正在寻找一些关于这方面的教程,因为我已经设法将自己与GET混淆,而POST-API总是让我混淆!谢谢你的帮助!如果您在使用“资源”约定声明路由时以标准方式使用new/create操作,Rails将使其变得非常简单。带有新模型的表单在默认情况下将使用POST等。遵循Rails的标准教程,您就可以了。