I am learning how to write APIs in Rails. I managed to write an API to create an object. However, I'm facing issues on how to invoke it.
Routes.rb
namespace :api do
namespace :v1 do
resources :company_donations
end
end
App/Controllers/Api/v1/Company_donation_controller has create method which requires 3 objects to be passed token, api_key and an object called donation with variables amount and comment.
Now I want to test my own API. How do I call this post API from a rake task? Use open-uri? How do I invoke following code?
post "http://localhost:3000/api/v1/company_donations.json", :token => "HusGbrnhi2s3EmUB7fHH",
:api_key => "f70aa490-dc2a-012e-da4e-442c03154814",
:donation => {
:amount => 101,
:comment => "Ordered 2 books"
}
Apologise for answering my own question. I eventually used - Nestful.post library helped.
Related
I'm trying to set up specs to properly run with my nested resource.
This is the test code I'm trying to properly set up
it "redirects to the created unit" do
post :create, {:course_id => #course.id , :unit => valid_attributes}
response.should redirect_to(course_unit_path(#course, Unit.last))
end
That essentially should try to create a nested resource "unit" for "course".
Unfortunatly I'm getting the following error on all POST DELETE and PUT tests
Failure/Error: post :create, {:course_id => #course.id , :unit => valid_attributes}
NoMethodError:
undefined method `unit_url' for #<UnitsController:0x000000059f1000>
That makes sense since unit_url should be course_unit_url but it's RSpec calling it...
How can I make RSpec select the right named path?
For all GET tests I passed the :course_id by hand.
This is what I did:
it "redirects to the created unit" do
unit_id = "barry"
Unit.any_instance.should_receive(:save).and_return(true)
Unit.any_instance.stub(:id).and_return(unit_id)
post :create, {:course_id => #course.to_param , :unit => valid_attributes}
response.should redirect_to(course_unit_path(#course, unit_id))
end
I decided that the point of this test was not that it created a new model and redirected it, but simply that it redirects. I have another spec to ensure it creates a new model. Another benefit to this approach is that it doesn't touch the database so it should run a little faster.
I hope that helps.
Edit:
I also just noticed I have this in my before :each section which may be relevant:
Course.stub!(:find).and_return(#course)
Edit again:
In this case, there was code in the controller which was doing the offending call. As per comment below.
I'm using Inherited resources for my controllers. And now i have model:
class Sms < ActiveRecord::Base
end
And i want controller for it, where i make defaults:
class Admin::SmsesController < Admin::InheritedResources
defaults :resource_class => Sms,
:collection_name => 'smses',
:instance_name => 'sms'
end
but i can not understand, why it still trying to get "Smse" model:
NameError in Admin::SmsesController#index
uninitialized constant Smse
Pls help.
The problem is that Rails doesn't know that the plural of Sms is Smses. If you go to the Rails console you should see that:
> "Sms".pluralize
=> "Sms"
> "Smses".singularize
=> "Smse"
When faced with a plural it doesn't recognise, singularize just truncates the final "s", which is why your app is looking for a nonexistent Smse model.
You will save yourself a lot of headaches by configuring Rails to pluralize/singularize your models correctly. In the file config\initializers\inflections.rb you should find some examples of how to do this. What you want is:
ActiveSupport::Inflector.inflections do |inflect|
inflect.irregular 'sms', 'smses'
end
Then I don't think you should need to put the defaults option in there at all - it should all work out of the box.
I wanted to know what the easiest way to rename a restful route is. Basically I have a controller called Employees and rather than have employees/new I want employees/hire to be used and achieve the same thing and make employees/new an invalid url.
For your specific need, the guide has exactly this example for new, edit, this should work:
resources :employees, :path_names => { :new => 'hire' }
http://guides.rubyonrails.org/routing.html#overriding-the-new-and-edit-segments
One of the best sources of data on routes is the rails guide:
Rails Guide on Routes, also the command
rake routes
This command will show you all the current routes.
But in answer to this specification question
if you look into your routes file you can create new routes
manually.
match 'employee/hire' => 'Employees#new', :via => :get, :as => 'employee_path'
the first argument matches what the browser is looking for.
The second argument is the controller and method.
The third is if it is a get, put, post, or delete call.
The fourth is the name for the path so you can access with the standard name_path type of call from code.
This makes sense?
In my app I've got various resources that I want to access via multiple URLs. For example, an invoice can be accessed via:
/invoices/:id
By the issuer of the invoice, and also via:
/pay/:payment_key
By the payer.
The latter URL does not require authentication (hence the secrefied payment_key).
The issue is how to get automatic URL helper methods for the custom URL. Usually you could use to_param to customize the resource URL (as described here), but that's not adequate in this case because I still want to retain the default resource URL.
If I create the helper methods by declaring a named route:
/pay/:payment_key, :as => :invoice_payment
Then I would expect invoice_payment_url(invoice) to include invoice.payment_key but it doesn't. Rails uses the invoice ID instead (similar to the behaviour reported here)
This seems like it's broken.
So I've been defining the url helpers for this resource manually.
def invoice_payment_path (invoice)
url_for :controller => "invoices",
:only_path => true,
:action => "pay",
:payment_key => invoice.payment_key
end
def invoice_payment_url (invoice)
url_for :controller => "invoices",
:only_path => false,
:action => "pay",
:payment_key => invoice.payment_key
end
Wondering if there is a DRYer way to do this?
RESTful is about resources. So are you sure the "payment" and "invoice" resources the same thing in your system? To me, it is more like a system design issue than a routing issue.
Another thought is using nested resources. You can view either "/payments/:id/invoices" or "/invoices/:id/payments", both make sense to me.
Yan
I'm upgrading my rails 2 app to rails 3. I use rspec, shoulda and factory girl in the test suite.
One particular pattern is causing an error I'm having a really hard time both researching and solving.
# cart controller spec
#cart = Factory.build(:cart, :payment_status => "authorized", :user_id => #user.id)
2.times { Factory(:cart_item, :cart => #cart) }
And I get this spec failure:
changes is defined by ActiveRecord
./spec/controllers/cart_controller_spec.rb:41
./spec/controllers/cart_controller_spec.rb:41:in `times'
./spec/controllers/cart_controller_spec.rb:41
calling the #times method is safe ( no error are thrown when I just put 2.times { puts "hi" } ) but I'm not able to see how #changes is being invoked here.
Do you have a column called 'changes'? I suspect it's clashing with ActiveRecord, you may need to rename it.