Changing/Upgrading Existing Models - ruby-on-rails

I starting building my app using nifty-generators for the user authentication because I'm new to Rails and it was the easiest approach. Now, we're looking to launch the app and I want to implement the popular Restful Authentication because we need some of the features it offers.
I've never upgraded an existing model in this way, and I'm wondering what the best approach would be. Should I strip out the user model-related stuff? Or will Restful Authentication just overwrite the commonly name items? Of course, I can go into the app and make tweaks based on any changes.
Generally, how would more experienced Rails coders approach this?
Thanks!

You might want to check out Authlogic instead. There's a good railscast episode where he implements Authlogic with nifty generators.

I would add another model and relate that via an has_one-relation..
f.e. adding a Account-Model (if your user-model already exists)
class Account << AR
belongs_to :user
end
class User << AR
has_one :account
end

If you've got a fair amount of tests, there shouldn't be an issue. Your suite will let you know if you've done something wrong.
Personally I would implement Restful Auth, by hand, on another project. Play around with it until you understand how it affects your user model, then copy over the code and any migrations you need.
A nice tutorial on Restful Auth and some cool extensions is here

Related

Sharing AR models between Rails applications

I have a problem that I have been trying to solve for a while now. I have 4 different Rails applications using the same database, meaning they need to use the same models and have the same migrations. I initially solved the problem by creating a Rails engine packaged into a gem, which then carries all the models and migrations with it. Now I realize that there are pieces of functionality that only one application needs, but the others do not - like for example the admin application needs to have methods for providing sortable tables for all models - the other applications do not need this functionality at all.
So my idea was to find a way where I can provide the "base" models from the gem, while augmenting these base models in my specific applications to add additional functionality when needed. What I tried first was inheritance:
class User < Base::User
end
This does not work though, because now you have 2 User models in your load path (User and Base::User) and when querying associations, it always picks the "closest" class for the associated record class - meaning when you have an Model::Account which belongs_to :user, it will pick Model::User as the association class, not User. I tried reversing the AR type compute method but this only resulted in more problems.
I can technically provide all of my models from the base engine (gem), but the issue here is that how do i extend these models in my application? .class_eval feels really really dirty, inheritance does not work, providing base functionality as mixins means the "base" models do not feel and look like models at all. My goal would be to cause as little friction as possible for the other developers, I want them to be able to define their models in the gem like they do normally and then also have an easy way to extend that functionality in other applications.
Has anyone solved this problem before or have any suggestions? Or how do you guys solve this problem in your larger applications? Any help would be appreciated.
This is mentioned in the Rails guides. It describes class modification with the Decorator pattern.

RoR - Project that exclusively uses another systems API?

Absolute beginner with ruby and with rails. My first full blown project will interface with an existing system through a REST api.
So it doesn't employ the normal ActiveRecord model and I was hoping for some examples of projects that replace the normal use of models with API calls. The entire CRUD set will require the app to make the corresponding API calls. I'd like to do this the right way, just don't know what that looks like yet.
Thanks! :)
Helpful links for googlers:
http://yetimedia.tumblr.com/post/35233051627/activeresource-is-dead-long-live-activeresource
https://github.com/rails/activeresource
I don't know of any projects that are open source that do this, but I'd recommend looking into Active Resource. It was part of Rails through 3.2, but has been moved to a separate repo for Rails 4. The idea is that it lets you replace database persistance with RESTful APIs, which sounds like exactly what you're trying to do. There is some documentation here which should give you enough info to get off the ground. There's also a pretty old Railscast on it, but I'm sure the concepts haven't really changed that much.
Here's an example from the docs that shows how to setup your "model":
class Person < ActiveResource::Base
self.site = "http://api.people.com:3000"
end
I'd suggest leveraging ActiveModel so your models aren't 'AR' backed, i.e. no persistance via AR. You'll handle CRUD accordingly in your controllers and craft your own 'business logic' that you can tuck into your ActiveModel.

Rails authentication with custom fields

I have a rails app where I need to add authentication. The problem is that I have a legacy database with custom user and password fields (t_user and t_pass). Plus, t_pass is not encrypted.
What I'm looking for is something like http_basic, but where I can have methods like current_user, and probably with a better user interface. I don't need validation, password reset, anything. Just a way to authenticate my way. I'd use restful_authentication but I'm on rails 3. I saw a fork that works with rails 3 but I was wondering if there is a better way to handle this situation?
It looks to me like you could probably do what you need using Devise and a bit of extra playing around. Specifically, you'll want to:
Make sure you create your user model table using your legacy auth table.
Override valid_password? on this model to check against your t_pass field.
Override self.find_for_database_authentication to find your model based on the t_user field.
If you want to support registration, you'll probably need to write a new encryption strategy as well.
Just a word of warning though: Storing passwords in plain text is very bad practice. If you have any choice at all, I'd seriously consider doing a migration of existing users into Devise's standard structure, with crypted passwords.
If you are looking for alternative gems to use then you can try Devise. You can extend/change the default settings to achieve what you want.
Devise and Authlogic are two potential options. Can't comment on Devise I'm afraid as I've never used it. Seems to be very popular at the moment though.
The following would get you started with Authlogic:
class User < ActiveRecord::Base
acts_as_authentic do |config|
config.login_field = :t_user
config.crypted_password_field = :t_pass
config.crypto_provider = YourCryptoProvider
end
...
end
There's a railscast on the basics of getting authlogic going.
The difficult part of this is that you would need to create your own crypto provider class as described http://rdoc.info/github/binarylogic/authlogic/master/Authlogic/CryptoProviders as authlogic doesn't provide a plain text password check method.
As discussed above, look into migrating your passwords to encrypted versions if that's an option for you, it will stop you from fighting against the auth frameworks so much.

Ruby on Rails User Setup

Currently, I have a 6-model ruby on rails application, that I added authlogic to.
The overall setup is
User :has_many categories, topics,messages
Categories has_many topics,
Topics has_many messages
(With and the corresponding opposite belongs_to links).
When I try to access current_user.categories.find(2), no results are returned in the controller.
Furthermore, when I try to run this
current_user.topics.find(params[:topic_id]).messages.build
Then,
#msg = current_user.messages.build(params[:message])
#msg.save
It doesn't save the user_id from the has_many.
All features of this program were working before the current_user directives were added in.
Am I making a mistake with the setup? Or with the execution?
Because the association isn't saving after the build, could I later add the user_id field in the model?
Sorry about all the questions, and thanks in advance.
I think your best bet is to go step-by-step. What does current_user return? Does the id of that user match one in your db? Does that user have any categories? Do any of them have an id of 2?
If you can isolate your problem to a single layer in your chained calls, it will be much easier to debug.
Thanks Kyle.
I've solved the problem using a filter in the model instead of using the controller to assign it on creation through association.
Current_user simply returns the record of the current user using authlogic.
I'm liking where the project is bow, and might deploy it after some visual tweaking, security, and more css :).
Callbacks and filters are amazing with whatever you are developing.
Also, if you need to get an variable from the application_controller to the model use the dollar sign ruby variable, not a class instance variable (at-sign).
Rails is so easy compared to a roll-your-own Php or sintra app.
Also, How many models are used for rails apps?

Has anyone written a plugin to add the final polish to ActiveResource?

I have been using ActiveResource in my Ruby on Rails applications for some time, and I am starting to really feel that it needs a final polish to make it go from "pretty nice" to "beautiful".
I would like to be able to use an ActiveResource as if it were an ActiveRecord. If I could use has\_many, belongs\_to and other niceties with ActiveResources, it would make my life easier.
So I looked around for a plugin to do just that, but haven't had any luck finding one. Has anyone written one? Does anyone know of an ongoing project?
Raison d'ĂȘtre
Let's say I have an application which manages Users, and another application which manages UserRequests. I would like to avoid any circular dependency between my applications, therefore I have decided that the Users application will be completely unaware of the notion of UserRequests. But of course, a UserRequest should belong to a User, and a User should have many UserRequests.
So, in the Users application, all I have is a User ActiveRecord, with all the necessary controller stuff to make it usable through ActiveResource.
The complicated stuff is in the UserRequests application. I have a UserRequest ActiveRecord, and a User ActiveResource. I would love to code the fact that a UserRequest belongs_to a User ActiveResource, and a User ActiveResource has_many UserRequests.
In another scenario where it could be the other way around (the ActiveRecord has_many ActiveResources, and the ActiveResource belongs_to the ActiveRecord).
Ryan Daigle proposed to do something similar with his Roxy gem. From his teaser section:
I hope to have an extension library up
soon that utilizes Roxy to provide
ActiveRecord-like association
definitions in ActiveResource.
The example he gives shows how it wouldn't be too difficult to implement with Roxy.
I just ran across the Hyperactive Resource plugin. I am looking at it right now... looks good.
The funny thing is that I had decided to write my own plugin, and I was looking for a good name for it. I wanted to find a name which would give the feeling that it was "ActiveResource++", an enhanced version of ActiveResource. I hesitated between "SexyResource" and "HyperactiveResource", and I decided that the former was not politically correct enough. So I started to write my HyperactiveResource plugin... until I wondered if someone else had already thought of that name. And it turns out someone did. And the plugin was there. Cool! But it's kind of scary how we developers think alike, isn't it? ;-)

Resources