Sinatra server with Rails/ActiveResource Client

139 views
Skip to first unread message

senihele

unread,
May 31, 2009, 4:44:11 AM5/31/09
to sinatrarb
I've set up a Sinatra app as a small web service. Things like get
'items.xml' and get 'items/:id.xml' work great with ActiveResource,
but I cannot get the post and put requests working. I'm not sure what
I'm doing wrong, but I can't seem to get anything out of params for an
action like post 'items.xml'

Any idea why this would be?

On a related note, I tried to skip ActiveResource by making an AJAX
post request (form_remote_tag), but sinatra interprets these request
as "OPTIONS" requests, not post request. Any idea why or what I can
do about it? Thanks,

Simon Rozet

unread,
Jun 1, 2009, 6:56:08 AM6/1/09
to sina...@googlegroups.com

Please paste your code

--
Simon Rozet <si...@rozet.name> http://atonie.org

senihele

unread,
Jun 1, 2009, 11:38:54 AM6/1/09
to sinatrarb
I managed to get the create action working by using HTTParty and
writing the methods myself. This isn't ideal, though - I'd much
rather use ActiveResource as it is what I am using everywhere else. I
seems if I send Sinatra the parameters as "param=var" it works (this
is what I'm constructing manually with HTTParty), but the xml hashes
Rails is constructing Sinatra isn't interpreting correctly. This is
what I have at the moment. I don't have an update action yet.

>> The Sinatra Server
# index
get '/urls.xml' do
protected!
Url.all.to_xml
end

# show
get '/urls/:id.xml' do
protected!
Url.first(:id => params[:id]).to_xml
end

#post
post '/urls.xml' do
protected!
content_type :xml
uri = URI::parse(params[:target])
raise "Invalid URL" unless uri.kind_of? URI::HTTP or uri.kind_of?
URI::HTTPS
#@url = Url.first(:target => uri.to_s) || Url.create_url({:target =>
uri.to_s}, 6)
@url = Url.create_url({:target => uri.to_s, :user_id => params
[:user_id]}, 6)
@url.to_xml
end

delete '/urls/:id.xml' do
protected!
@url = Url.first(:id => params[:id])
@url.destroy
end

>> The Rails Client
- LINKS_CONTROLLER

# GET /urls
# GET /urls.xml
def index
@links = Link.find(:all)

respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @links }
end
end

# GET /urls/1
# GET /urls/1.xml
def show
@link = Link.find(params[:id])

respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @link }
end
end

# GET /urls/new
# GET /urls/new.xml
def new
#@address = Url.new

respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @link }
end
end

# GET /urls/1/edit
def edit
@link = Link.find(params[:id])
end

# POST /urls
# POST /urls.xml
def create
@link = LinkService.new('user','pass').post(params[:target],
current_user.id)
redirect_to '/links/' + @link["url"]["id"]

>> NOTE - I kept getting a bizarre HTTParty related URL rewrite error when I tried to use Rails named paths here (links_path works, but link_path(@link["url"]["id"]) does not - even manually putting in an ID or using the whole object), so I ended up having to construct the URL explicitly.

end

# DELETE /urls/1
# DELETE /urls/1.xml
def destroy
@link = Link.find(params[:id])
@link.destroy

respond_to do |format|
format.html { redirect_to(links_url) }
format.xml { head :ok }
end
end

- LINK.RB (ActiveResource)
class Link < ActiveResource::Base
self.site = "http://user:pass@site/"
self.element_name = "url"
end

- LINK_SERVICE.RB (HTTParty)
class LinkService
include HTTParty
base_uri 'site'

def initialize(u, p)
@auth = {:username => u, :password => p}
end

def post(url, user_id)
options = { :query => {:target => url, :user_id =>
user_id}, :basic_auth => @auth }
self.class.post('/urls.xml', options)
end
end


If it would be helpful to see more of the code, I can probably provide
more of the site, but that's all the relevant parts. As you can see,
using HTTParty and ActiveResource is really an inelegant solution and
I really prefer the simplicity of AR. Any thoughts?

senihele

unread,
Jun 8, 2009, 4:36:04 PM6/8/09
to sinatrarb
Does anyone have any thoughts on this? Is this even supposed to work
as I hope it will?

gsw

unread,
Jun 9, 2009, 10:36:40 AM6/9/09
to sinatrarb
Did you try to output to console/log the stuff it is having trouble
with?

Also, in the top line of the get/post you might want to set the header
to be xml.

like:
get '/urls/:id.xml' do
headers["Content-Type"] = 'text/xml; charset=utf-8'
...
end

And you'll want something to return errors in an expected format that
can be handled by the client vs. html:
error do
headers["Content-Type"] = 'text/xml; charset=utf-8'
"<error>#{request.env['sinatra.error'].to_s}</error"
end

And to ensure that error block is called and that you have adequate
sinatra errors output, IMO you should:
set :raise_errors, Proc.new { false }
set :show_exceptions, false
set :dump_errors, true
set :clean_trace, false
Reply all
Reply to author
Forward
0 new messages