Super-simple updates app in Rails - ruby-on-rails

I have to cook up a super-simple Rails app with the following functionality:
Only one model: Update. Updates are simply news that my client will be publishing on the site, i.e. basically mini blog posts. An update has three fields: headline, text (both mandatory) and image.
The client will need to log in to create, update, & delete updates. No roles and authorization levels are necessary — just a single login / password combination for the above tasks.
It's desirable to have a very basic WYSIWYG (for inserting links, etc) in the UI for creating & editing updates.
It's been a while I've done something similar, so the question is: is it advisable just to roll everything from scratch or are there gems I should consider?
(I'll be probably using AWS and CarrierWave for images).
Much thanks!

Simplest way to achieve this (and yes, it will be relatively simple) will be to use the Devise gem with InheritedResources. Here's how:
Flow
Firstly, you'll want to ensure you're able to give the use a place to compose & submit the updates. To do this, you'll want to create a simple backend (admin) system, to give you a separate space to update your backend:
#config/routes.rb
namespace :admin do
resources :updates, path: "", except: :show #-> domain.com/admin/
end
root: "updates#index"
resources :updates, path: "", only: [:show, :index] #-> domain.com/:id
The importance of this type of system is relevant.
The issue I think you're alluding to is the way in which you won't be able to either create or access the various mini-updates from a "protected" area. Using the method I'm detailing will only only provide this area, but also give you the ability to store the data correctly.
--
Controller
To get this to work, you'll need two controllers:
#app/controllers/updates_controller.rb #-> for general users
class UpdatesController < InheritedResources::Base
#InheritedResources will create relevant CRUD resources
end
#app/controllers/admin/updates_controller.rb #-> for admin
class Admin::UpdatesController < InheritedResources::Base
before_action :authenticate_user! #-> for Devise
#InheritedResources creates relevant responses
end
The above two controllers are really the core of what you need. They provide the CRUD functionality for both the admin and `general areas of your app - giving you the ability to provide the users with the ability to upload as they require.
The biggest thing you need to consider is the authentication. This is handled with Devise (which I'll explain below). The thing you need to consider is the authenticate_user! call - this is what determines whether the user is able to invoke the methods, depending on whether they are logged in (maintain an active session) or not
--
Devise (authentication)
The Devise gem will be what you need to get the authentication of your app sorted. This is what you're asking about -- and simply, it's a job for Devise.
There is a great tutorial on how to handle this here:
The bottom line with Devise is that you need 3 things to get it working:
A User model
A users table
The Devise columns & system installed
Without over-burdening you, I'd just recommend using the controllers I put up above (with the corresponding views), the routes, and then Devise

It's not a gem, but you could look at Rails Composer: https://github.com/RailsApps/rails-composer - they have templates for generating apps that meet your needs. It lets you set options to help you customise them further.

Related

When using cancancan with devise, does devise need to be added to ability.rb?

Question: when using cancancan for authorization and devise for authentication, do I have to define any authorizations for the devise part of the app, or does devise take care of everything itself?
Example
For example, for (all) other resources, we should place load_and_authorize_resource in the controller of that resource so that users who should not access it are prevented from doing so. Then, to allow access to those should have access, we can define abilities by adding code like this to ability.rb:
# ability.rb
can [:index, :show], [Patient], user_id: user.id
Back to my question - do I have to add load_and_authorize_resource to any of devise's controllers and define permissions for devise controllers in ability.rb? OR does devise take care of all that without the developer having to do anything?
We obviously don't want to allow one user to change another user's account info!
It's important to distinguish between devise authorization part of account info (session creation/logout/email+password+restoration/changing if you have that enabled) and any other custom logic and data related to it (for example - names, shoe sizes, whatever) that is kept inside or accesses the same model.
Devise controllers, if you did not change them much - are very simple and do not need additional access control because by design user is only able to edit their own auth data (they simply do not handle user id from outside thus there's no way to tamper it). Moreover just adding load_and_authorize_resource will at least have no effect or more probably will interfere with existing devise code because it was not designed around cancancan.
But if you have your own controllers for user profile(s), like user index, admin editing other's profiles etc - obviously, you have to facilitate access control there.

How to be RESTful in Ruby on Rails?

I have a decent amount of experience with rails, but I've always been a bit ad hoc with my development methods. I'm curious about how to be properly RESTful in rails. Here's an example of an app I'm working on now:
I have a few models, including a User, Pack, and Product model. The models each have a controller associated with them. If I want to create a new page called 'Dashboard', on which the User can create new records on the Pack model, as well as see their account information, how do I do this in a restful way? Do I create a new controller called Dashboard? Or do I add it to a controller that defines my 'Static Pages'? What's the best practice regarding pages that aren't exclusive to the actions on one model?
Thank you in advance!
Yes, basically you want one controller per resource. In this case the resource is a combination of things but since you've identified a singular meta-resource (a "dashboard") it makes sense. So, I'd create a DashboardsController and then have a route like:
resource :dashboard, only: :show
Then you can use dashboard_url for links to the dashboard.
NOTES: The singular resource in the routes file is important because it indicates you don't have a list of resources, just a single one. This means there won't be an index action and the show action will be the default -- thus dashboard_url doesn't require a resource to show to be passed to it. And, regardless, controllers are named in the plural -- thus DashboardsController.
I would create a DashboardsController despite not having Dashboard model. Then to maintain REST principles have a controller method :new and controller method :create. Simply disply the information on the dashboards/new.html.erb but have the form post to the :create controller action.
To supplement the answers already given, REST really exists to make an easily-consumable API. (Notably, Roy Fielding's work is in the area of APIs, and REST is built on top of HTTP methods that HTML doesn't allow.)
This has been a common stumbling block since RESTful routing debuted in Rails; people get the impression that every controller now needs to be RESTful and that the front end and API should never diverge. Frequently, though, the front end and API have different needs.
For resources you want to be accessible via an API—Products, Users, Packs—trying to be RESTful is ideal. For those sorts of uses, pdobb's advice to have one controller per resource is generally exactly what you're looking for. They make sense in the context of an API being consumed by a machine.
But what about the dashboard? Dashboards are generally an HTML view intended to be rendered in a browser and viewed by a human being.
Does a "dashboard" resource make sense in the context of an API? Would it make more sense to instead make that data available in other resources? Is that data available in other resources?
Even if a "meta-resource" aggregating data still makes sense, would it be more logical if the API version had another name, like AccountSummary?

Path security and before_filters rails

I am currently creating an app where users can create and apply for jobs. However as I am fairly new to rails I am facing a fairly significant security feature in that if any user knows the correct path, for example:
localhost:3000/users/user_id/apps
Then they can see any application made by any user for any job!
I am fairly sure that I need to use a before_filter to check that the current_user.id matches either the user_id found in my jobs table for each job or matches the user_id found in my applications table.
I am really not sure how to structure this though or where to apply the filter - for example is it better to create the filter in the application controller and then apply a skip_before_filter instance where needed.
Any help people can offer on contructing this code and where to place it would be much appreciated! Thanks :)
Before you start looking at authorization solutions such as cancan, a simple approach is to avoid doing
App.find params[:id]
Since an app is associated to a user and you've got current_user setup you can do
app = current_user.apps.find params[:id]
Which will only find apps associated with the user, no matter what the parameters to find.
Where cancan really comes into its own is when you need a more complicated who can do what system. For example a user might be able to edit any job they've created but view (and not edit) another set of jobs.
For example
can :manage, Project, :user.id => user.id
can :read, Project, :department => user.department
This would allow users full access to any of their projects and read access to projects in their department
Another thing about cancan is that rather than having before_filters or macros scattered around your controllers you declare the rules in one place, so it's usually easier to see what's going on. There's loads more info on the cancan wiki an a railscast too.
You are right a before_filter might be an sollution but its not the state of the art solution. Theres a railscast for that,...
http://railscasts.com/episodes/192-authorization-with-cancan/
When your using cancan but not devise you need to create the current_user helper that should return the User object of the currently logged in user...

Rails full-fledged admin control panel

I'm wondering what's Rails approach when it comes to creating a full-fledged admin control panel. And by full-fledged I mean a real control panel that could be used on a professional level, not personal/internal scaffolding.
I don't believe its stored in the same folder as the user interface as it's shown in the blog screencast or in Getting Started with Rails tutorial!
I'm certain the same model will be used everywhere but what about the views?
Please explain in details. I don't want to use my PHP mentality when starting my first real project in Rails.
Thanks.
here you can find a list of rails plugins/engines to manage admin interfaces:
http://ruby-toolbox.com/categories/rails_admin_interfaces.html
I've used a bunch of them (typus and rails_admin), not bad at all.
also check the recent released ActiveAdmin
http://activeadmin.info/
As hinted at by the previous answers namespacing is useful to keep admin functionality neatly separated from other user functionality, for example:
# In your routes
namespace :admin do
resources :stories
resources :editors
#etc.
end
Then you'd put all your admin controllers in an 'admin' subfolder and always require an admin to access them:
# app > controllers > admin > stories_controller.rb
class Admin::StoriesController < ApplicationController
before_filter :authenticate_admin! # assuming you're using devise
def index
#etc.
end
end
The advantage of this is you only have to check for admin in one place (the before_filter of an admin controller) rather than having to put conditionals everywhere in your normal controllers / views.
It depends on the nature of your application, but there's nothing wrong with having the admin functions in the same view as the user; Just test your permission role before showing certain part of the display.
If you really need an admin only interface, you could namespace some controllers and views. There are other posts that deal with how to do this, such as The Rails Way - Namespaces

Authentication with Ruby on Rails & Devise

I am about to build a new site in ruby on rails for residents at my college.
The site will allow residents to change their passwords for the college-firewalls (which means there are certain requirements).
On the site, each resident will have an account with a number of data assigned to it, and for this I need some authentication.
I've been studying Devise for almost the entire day now, but im starting to wonder if I have a too complicated task, to complete it with Devise.
Problem is, I need the passwords to be stored with DES-encryption, something Im not sure if Devise can handle.
Another thing is, users can't make their own profile. Admins will do that (to ensure correct data), which means that user-creation is not the default one. Since there are no controllers for this, is it even possible to do it that way?
I'm not sure if I should keep on going with Devise, or bite the bullet and write it all from scratch instead. Some opinions would be appreciated.
This page on the Devise wiki ( https://github.com/plataformatec/devise/wiki/How-To:-Create-a-custom-encryptor ) tells you how to set up a custom encryptor.
To make it so that admins create a user, remove the :registerable module from the User model. Then add a user resource to your app, example:
scope 'admin' do
resources :users
end
Set up the new/edit pages with your profile fields, etc., normal rails programming.
For an example using CanCan to control access to the users resource, have a look at this post: http://zyphmartin.com/blog/manage-users-with-devise-and-cancan.
If devise does not exactly do what you need, maybe this recent webcast from Ryan Bates will help you.

Resources