I've got a Twitter app. All our users come directly from Twitter. This means, you cannot do any significant interactions with the app unless you are logged on, from Twitter. Our app caches (saves the user's Twitter data in the db).
It is possible to integrate Capybara with Omniauth. For example to test OAuth integration with Twitter. I've read a few articles online about this. However, the tricky part is getting it to work with Devise + Omniauth (I've only seen a scarce number of articles, have tried them to no avail).
Second, I've also looked into testing file uploads to S3, which make it quite difficult, since we are uploading directly to S3 using JS (Uploadify) and then instructing Carrierwave to grab the file.
A few have mentioned that it is best to provide mock data instead of trying to test OAuth directly. I guess, what they are trying to suggest, is to seed the test database with mock Twitter data. That way, I can test the user directly in the app. Without having to worry about how to get testing with Rspec + Capybara + Devise + Omniauth + Twitter to work.
I could do the same for file uploads as well. Does this make sense? Is this a sensible approach?
By seeding the database with the appropriate data beforehand, you avoid dealing with all the integration testing issues of Omniauth etc. As the library itself is already tested anyhow, you also avoid and unnecessary overhead.
So yes - seed your db with the data right away.
OmniAuth has helpers for integration testing.. i wrote a post about that, it may help you..
Related
I have a web app implemented in Ruby on Rails 4, need an Android native app for it, I am really new to mobile development.
I am a bit confused as to what the mobile-web architecture should look like in this case. I've done some research online, there seems to be a few ways of doing this, but I still have some questions that I haven't been able to find answers for. Thanks in advance for all pointers.
1) do I really need a separate API for the mobile app? what are the issues in using my Rails app's existing controllers with respond_to format.json?
2) I've seen some online examples that suggest using an separate API namespace in the Rails app to serve mobile requests, e.g class Api::ApiController < ActionController::Base for the new controller, then add namespace :api do in routes.rb. With this approach, doesn't it imply that I'll need to duplicate quite a bit of my controller functionality in this new namespace just for mobile?
3) Regarding authentication, many examples suggest using token authentication, is the built-in Rails sessions management framework not good enough for mobile apps? or is it because session cookies work completely differently in a mobile app?
Appreciate your time.
It is not necessary, but it is, like you said, considered a best practice.
1+2) Having same controllers with respond_to/respond_with logic is a nice idea at first sight. But, from my experience, I can say, there always comes a day where API code start to differ with HTML client code. The mobile client might have a different UI and it is just natural that it will expect to consume your data another way as your web client does. The web client is specialized to one use case where an API should be more generic allowing multiple consuming ways.
The second issue that will arise is the fact that you cannot rely on your mobile users to always have the latest app version where with a webapp you can. So for the HTML app you can easily introduce non-compatible changes because you are delivering a proper client right within where for the mobile API breaking the API is at least concerning. Perhaps, you will want to maintain a backwards compatibility which will make your all purpose controllers ugly as hell. And without a proper api/v1 namespace you even can't have two different API versions at the same time.
You can avoid duplication of your logic by keeping your controllers very skinny and move the logic out into models (Service Objects are models too, not only Active Records).
3) Your mobile HTTP lib will to a high probability have a proper automatic cookie management. Having token based authentication is just again a best practice. If it is just a token vs session_id within cookie, there will be not much win. I can only think that it will be automatically secure against CSRF attack and you can disable this protection entirely for the API because your website users won't be allowed to consume the API, just by logging in to the site (an additional benefit perhaps). With session based authentication you will have to generate a CSRF token on first API request and set it within X-CSRF-Token cookie.
The big advantage of token based authentication is that it is extendable to more security, like introducing expire tokens, HMAC tokens etc, whereby session authentication is not.
See Using Sessions vs Tokens for API authentication
I would also encourage you to look at json:api. It comes from the creators of ember.js, who have thought about minifying decisions to take, when building APIs. Another interesting thing is an active_model_serializers gem. An intro to it is given within Rails: The Next Five Years by Yehuda Katz
I have 2 different Rails application and I want these apps to send and receive information via an API. What is the correct way to do this?
I was trying to use this resource but I don't quite understand it: http://api.rubyonrails.org/
(I am not sure how to make the call for the different methods. Some methods show an URL which I guess I wouldn't have too much problem implementing, but what if the application is within the same server, what would be the correct way to call a corresponding API method.)
Is there a recommended beginners resource out there?
Thanks.
api.rubyonrails.org is Ruby on Rails documentation, so this is API of RoR. What you want is external HTTP, probably REST and probably JSON API.
There are many resources on building REST API's. In general you have to prepare some endpoints that application can send request to and handle responses.
Take a look i.e. on railscast about using active model serializers. This would be the part where you give other application endpoints to get or change data.
Normally you would stop here because in most cases you set API for other applications (like mobile or javascript applications). But in your case you will need something to send requests. There are many gems that allow that, but I find Faraday gem most useful.
I was using the Twitter Widget for the longest time but I was looking to step it up a level and add additional styling and filtering. Recently I got started with the Rails Twitter Gem and so far so good, but I wanted to be able to link back to profiles wherever #username appears.
Looking around it seems that Twitter Anywhere is the way to go, but I was wondering if there was a better implementation in a Rails environment? Perhaps a gem that loads the required JS files and provides helper methods?
Also I should note that I don't necessarily require all of the functionality that the anywhere api offers, at the moment my main focus is just to provide the #username links (though it is certainly nice to have the option for future expansion).
It turns out that Twitter Anywhere might have been a little overkill for what I was trying to do. All I really needed was the following helper method as mentioned here
def linkup_mentions_and_hashtags(text)
text.gsub!(/#([\w]+)(\W)?/, '#\1\2')
text.gsub!(/#([\w]+)(\W)?/, '#\1\2')
text
end
I've searched for "multiple files upload in ruby on rails" and the plugins that were suggested always displayed multiple <input type="file" ...> tags. I'm looking for something where I can choose multiple files in the same browse file window, like when uploading photos on facebook.
I've found this one, but it requires some under-the-hood coding to be used in RoR (it is ready for PHP).
My requirements are really basic: I only need to be able to upload files facebook-like. No visual effects needed, or progress bars or whatever. So maybe I'm thinking about implementing my own uploader, but I don't know where to start.
So if you got either 1) a suggestion of RoR plugin that might do what I just described or 2) tips on how to implement one myself, I'd be very glad to hear them.
I've heard good things about Plupload and, to a lesser extent, Uploadify. The former uses a variety of techniques transparently to try and achieve multi-file upload (using the HTML5 API if possible); the latter only supports Flash (though this is what many users will end up using).
Integrating these with Rails is just a matter of implementing the API they expect, which is fairly straightforward.
Here is a post by someone who has taken the effort of making sure CSRF protection and Flash session cookies even co-operate. http://planetrails.com/plupload-with-rails-3
I have not followed that particular guide myself, but it seems correct.
I've had good success with the jQuery File Upload Plugin. It uses both the HTML5 "multiple" attribute for file inputs and drag-and-drop uploading.
If you're using paperclip and jQuery, you can get it integrated in your app pretty quickly.
I have always used Authlogic in Rails 2.3 but now that I am using Rails 3 I think I might try out a new authentication solution.
How does Devise compare with Authlogic? What are their differences?
I've used them both, but not extensively. In my last project, I gave Devise a shot. I ended up using Rails-Warden instead.
Devise is a full authentication framework built on top of Warden. To customize its looks, you use generators, then edit the resulting views. Its routes, and view logic are hard coded. For example, successful login will always take you to /session/new? This was a dealbreaker or me, I wanted my users to end up on "welcome/index". Devise is not as well documented, or intuitive as authlogic.
Warden is a middleware framework Devise is based upon. It has plugins for many web authentication schemes (fb, openid, oauth), and it is easy to build a plugin for your own authentication back end. It comes with no UI, and docs are not as good as authlogic.
I ended up using rails-warden because I needed to plugin multiple custom authentication schemes.
Also, see OmniAuth answer below, that's what I am using in 2012.
for devise, if you want to send successful login to "welcome/index" you add to routes.rb
namespace :user do
root :to => "welcome#index"
end
as documented https://github.com/plataformatec/devise/wiki/How-To:-Redirect-to-a-specific-page-on-successful-sign-in
personally, i like devise. it think it's great and i guess you can call it "opinionated" but those opinions can be easily overwritten.
I found Devise too opinionated for me. If you just want to accept the way it does things out of the box it is good and easy to get going. I had some specific requirements and found myself writing things to get round Devise so ended up ripping it out and updating Authlogic to Rails3 instead.
Like the original questioner, I too had always used AuthLogic in the Rails 2.3 days but made the choice to use Devise when AuthLogic wasn't ready for Rails 3.1 (when it was at the RC stage). Overall I've made Devise do what I want but I'm unhappy and wish I hadn't made the change.
User Authentication seems simple on the surface and an ideal thing to "componentize" but so many times you want to let a user engage with your site fully before requiring login and Devise makes this harder.
Yes features like putting after_sign_in_path_for / after_sign_up_path_for into Application Controller work but these functions are really intended to do nothing more than return a path and if you're using Devise you'll find yourself sticking big blocks of code into them. It works but having your own users controller to handle user related actions is, to me, more elegant.
If you need multiple OAuth authentication to Twitter, Facebook, LinkedIn and Google, you can use the OmniAuth gem along with Authlogic. Easy to figure out and gives you complete control over what happens as users authenticate from different social sites, which you do in authorizations_controller.rb.
I like Devise. You can use OmniAuth with Devise too. I think that the Devise project is very active, and it has a big support on the internet.