rails 4- where to put user function - ruby-on-rails

I am building a sample app for learning rails 4, and I'm a little confused on where I'm meant to build certain things. For example, I want to check if a user is logged in, and if so, display their account balance in the header (a partial).
Thanks to Michael Hartl's tutorial, I have a function to check a user's login status in the session helper, which is included in the application controller and can therefore be accessed in the partial.
Since the balance is tracked in the Users table, do I build a function get_balance in the Users model? Or should I create a function in the application helper? If I do build it in the application helper, is this auto-included in the application controller, or do I have to include it specifically? If I don't build the function in the model, can I still access the User object?
Thanks for your patience with a noob.

Since your users balance is a column in Users table, it is already there for you as a field (most possibly user.balance). And yes, this is where you should store it. You might use helpers for stuff that is related to general layout of your application and use combination of partial view and layout to spread it around.

Since it's already on your table, assuming your user is logged in, you could just call
current_user.balance
But it sounds like you want to add onto the data given,
I would suggest perhaps using a Rails decorator for your user model.
Basically a decorator adds an object-oriented layer of presentation logic to your Rails application.
I use the Draper Gem

Related

Rails: How to implement login and authentication where i have five different user models in rails?

I'm fairly new to rails. I'm having problem on designing the model classes. So this app will be used by 5 different users(Students, Teachers, Head and Coordinator). They each are different users to login into the website and have different functionality (example: Head makes an event. Students register for an event. Coordinator sets who can be head etc). I have created all four models with USERNAME and PASSWORD on each models.I don't have user model right now because the users in this app are these 4 models. Now, while making login page, i'm having hard time on implementing the best way to authenticate the users. For example, If a Head puts its login credentials, the app should identify that user that logged in is Head. What approach will be best to encounter this?
Also, after not figuring out the way to approach this. I was thinking of using devise and CanCanCan gem. But the same promblem comes in even if i use this gems.(i maybe wrong)
Do not create multiple models for different kinds of users. This is almost always not what you want. Instead add a column called role of the type enum which contains all of the kinds of roles you want to add like Sergio pointed out. Your comment about having too many attributes on one model is a non issue compared to the one you are planning to create with 5 user models.
It sounds like you are possible putting too much data on the user model if that is your concern
and have different functionality (example: Head makes an event. Students register for an event.
For this you want a permissions system such as cancancan where you can specify which features of the website each role has access to.

Best practice when developing an RoR application

I am currently creating an application. It's relatively simple, lets say for now it only contains users & posts
What I am trying to do is display basically a blog with a new post form at the top in case the signed in user is admin.
I have two options:
I can use an index for posts and keep it all within the posts controller. I could add a form to the index.html.erb which checks for admin attributes.
However, I will most likely use the index functionality later on in other parts of the app.
Second option would be to create a static page called blog and render the form view and all posts.
Both should be possible, but what is the "rails way"? Or is there no best practice?
Controllers should be RESTful, and should be appropriately named for the resources they manipulate.
The index action of your PostsController should have one purpose ... providing appropriate information relating to all of the posts to its view. The exact output of this could change within the view depending on whether you're logged in as an admin or not, but essentially the role of that action should be restricted to that function.
I would advise you to take a look at the CanCan gem and think about how you could use that to authenticate users, providing appropriate page content to admins and normal users alike.

Rails application with multiple roles

I have a rails application with 2 roles, say admin and user. But the thing is, The admin doesn't use a backend like ActiveAdmin for example. I want both Admin and User to see the same views, but depending on the role, I restrict what they can see. I'm using Cancan, but since for example both admin and user can see the product page, I end up with many conditions inside the view and controller actions stating for example if this is an admin show that, if not then show that instead.
So I don't really think that this is the "Rails way". I end up with many repeated code, and code inside the views which doesn't really support the idea of keeping the logic away from the views.
So my question is, What's the best way to implement such a scenario with many roles but the same views.
Thank you.
I'm thinking of two options currently, but I don't like either. One is to redirect the admin to another view, but this way most of the view is the same hence it's not DRY at all.
Option 2 is to use the exact same view, but add many conditions in the view, so I end up with a huge complex view with code. I'm trying to find a way that keeps things DRY yet simple, and keeps the views code free.
You can have the admin module under seperate namespace and users as the default namespace. You can extract the common code under partials and use the same in both admin and user module.
This way you can separate the code for user and admin, and if sometime in future if you decide to go for a different views for admin and user. It won;t be much of a task.
Have controllers as
app/controllers/admin/articles ------ for admin users
app/controllers/articles ---- for normal users
and
views
app/views/admin/articles
app/views/articles
app/views/shared
There are different possible approaches. A variation of the 'decorator' pattern would come to mind as described here
It's some time I last read it, but I think the basic idea is to put the logic in the model or helpers. As soon as a user logs in and you can see if he is an admin or normal user you have methods that return the necessary html or text.
A more simple approach would be to just have two partials for everything. Either as Ross says in a separate admin namespace or even simpler (but more work if you later need to change that) just like _user_view_something.html.erb and _admin_view_something.html.erb.
Somewhat similar thoughts go into the DCI pattern. This Blog gives some nice overview how this could play into Rails. The article is more about permissions, but again the basic idea is to supplement the user object with the necessary functions.
So you have the basic "do_something" method which renders something or places some information in the view and replace it with the one that fits to the role the actual user has.

How to access logged in user from controller in rails 3

I'm trying to create a login system in Rails 3 where I can access the logged in user not only from the views but also from the controller/model level. The reason is that I want to adapt functionality according to a privilege system where logged in users may execute different functions than those that are not logged in.
Up to this point, I tried to implement the login system from railstutorial.com, chapter 9.
When I use the login system only from the view, it works. However, if I try to use the system via a controller, I get the error undefined method 'cookie_jar' for nil:NilClass.
Thank you for any help or best practices you can provide for creating an authentication system where the logged in user can be identified from a controller.
The best advice here is probably "don't". If you want an authentication system, use something like Devise - which has had a lot of time and effort spent making sure that evildoers can't get in
If you want different users to execute different functions, this is access control, and for that you probably want something like cancan or ACL
And you want access to the logged in user from the model level? Again, the best practice is "don't". The model should have no interest in the currently logged in user - that is a matter for the controller.
(That said, rules are sometimes made to be broken - if you are doing an audit trail and need to store information about the user who made a change, for example, passing the currently logged in user to the model may be the best answer ....)
And finally, if you really, really want to do it all from scratch, take a look at this railscast
An extremely simple way is to do it as mentioned in railscast episode : http://railscasts.com/episodes/20-restricting-access
As mentioned in the screen cast, you can use the plugin acts as authenticated (http://www.railsrocket.com/acts_as_authenticated-plugin) for all your user model needs.
If everything done according to the tutorial you should be able to get current_user from both controllers and views. There's also another tutorial on authentication on asciicasts.com by Ryan Bates. You may want to explore it if you are just starting Rails, but for real-life applications it's highly recommended to use Devise or AuthLogic, which are thoroughly tested and constantly evolving.

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?

Resources