How to create an admin area in Ruby Volt? - voltrb

I've been playing a lot with Volt lately, and would like to figure out how to create an Admin area. The documentation has a section on restricting models for users, but it's still in the TODO list. Would like to know if there is an elegant way to do this yet?
I've figured out how to check whether a user is logged in or not, but would be cool to add some kind of role management (like the cancancan gem for RoR).
I'm new to all of this so I hope this isn't a stupid question, maybe I'm missing something obvious - but any help would be greatly appreciated!

I was trying to do the same thing, but I found this one here.
So it seems to be work-in-progress.
:(
#jjuliano: March 2 2015
so roles aren't built in directly, but it will be really easy to add that in. #ryanstout will it be something like this?
def admin?
current_user._permission == :admin
end
class Todo < Volt::Model
if admin?
permissions do |state|
allow
end
end
end
#ryanstout: March 2 2015
more like this:
class Todo < Volt::Model
permissions do
allow if admin?
end
def admin?
Volt.user.admin?
end
end

I've been playing with using components to render different "sections" of a web app.
For example, in my index.html I have something like the following:
{{ if Volt.current_user.is_admin }}
<:admin_section/>
{{ else }}
<:peon_section/>
{{ end }}
where my app has two components, admin_section and peon_section
For more information about components, see the volt user docs at http://docs.voltframework.com/en/docs/components.html

Related

How to test one page where its content differs with permissions user has in Capybara, SitePrism

Creating tests in Ruby, Capybara using SitePrism. I have faced situation, where I have one site but content of the site depends on permissions the user has. For example element "admin" in menu is visible only for admins e.t.c. One major difference is that admins has their own subdomain like admin.example.com (site for normal user is example.com).
I have to test it both from admins and users point of view and I want to avoid creating two almost identical page objects.
Is there a right way to solve this?
So there are a variety of tools at your disposal here.
#all_there? will check if all declared elements are on the page. Furthermore this can be restricted down via the Use of DSL statements such as .expected_elements
I would advise you going back to the README which has a lot of new info in the last 6-9months and checking on it.
In terms of scoping so there is the concept of a user and an admin, that's also easy to partition using variables in your ENV hash perhaps and setting the url accordingly. Again there is documentation on this on the SitePrism docs/Github.
If you feel as though this still isn't working or there is an issue, open an issue request here: https://github.com/natritmeyer/site_prism/issues
class ExamplePage < SitePrism::Page
...
element :test_element, '#test_element'
...
end
...
let!(:example_page) { ExamplePage.new }
context 'situation 1' do
it 'displays test_element' do
...
expect(example_page).to have_test_element
end
end
context 'situation 2' do
it 'displays test_element' do
...
expect(example_page).to_not have_test_element
end
end

Using CanCanCan with views to hide/show content - Advice

This might be an obvious issue for some one good with CanCanCan, but I am finding it hard to wrap my head around it.
I got an application that has many roles around it (campus_rep, campus_manager, operations_manager, admin etc). They all have acces to an 'admin' section but will see different menu options based on their role.
For example:
Admin can manage all 'Customers'
Operations managers can manage customers for the schools they belong to
Extract of ability.rb
if user.role == 'admin'
can :manage, JobApplication
elsif user.role == 'operations_manager'
can :manage, JobApplication, school_id: user.schools.map(&:id)
elsif ser.role == 'campus_rep'
# blah but nothing to do with JobApplication
end
I have been thinking to use if can? :manage, Customer but then even 'operations_managers' don't pass it which makes sense.
What is the recommended way to get out of a similar situation?
I tried if can? :manage, Customer.new(school: current_user.schools.first) which kinda works but looks not alright.
I though of doing some thing like adding can :see, JobApplication to both 'admin' and 'operations_managers' and then doing the check like if can? :see, JobApplication.
What is recommended? Is there any better way? Hopefully there is...
Also highly appreciate any advice in the matter
Your code mentions JobApplications but your question is mostly about Customers : I'll talk about Customers but the principle is the same for any model.
If I understand you correctly, you aim to pass a collection of customers to your view. But you only want the view to show those customers that your user (say an operations manager) is allowed to manage.
In that case your controller or view template code can filter the customers according to ability. So you would do something like
#customers = Customer.find_each.select { |cstmr| current_user.can? :manage, cstmr }
This will be quite slow if there are a lot of customers, so some programmers will try to bypass cancancan and design a database query instead. For example, you could query the database for all customers belonging to a particular school.
Your main misunderstanding is that you are trying to test abilities based on classes. However, your rules are based on individual objects. This is normal, so the normal way is to test each instance.
Reference: http://www.rubydoc.info/gems/cancancan/1.13.1#2__Check_Abilities___Authorization

Understanding routing in rails

Ok first off I have to say I'm very new to Rails. I have spent the last few days going through tutorial after tutorial and still missing a few concepts. Mainly because I just want to start off with a simple site structure but every tutorial is either a shopping cart or a blog which are more applications within a site. I have some pages on my site that will have photo galleries that are database driven but for now I'm just trying to get some answers to these questions.
Site structure:
home | photos | about | work | contact
Work has sub pages for example:
html | ruby | rails | bla-bla
Controllers:
Do I need to set up a controller for every new page or could I have one controller that handles all main level pages.
If I could use one controller how would that work and would I need to define an action to handle each page ( view ) like
class MainController < ApplicationController
def index
end
def photos
end
def contact
end
# and so on ......
end
Routing:
How would I route the above.
Whats the difference between a resource and a *get
get "photos/photos"
resources :photos
When I setup a controller for a specific page like.
rails g controller Contact contact
It creates a folder inside my views called contact and inside it is a view called contact meaning my url is contact/contact
it also adds a route get "contact/contact"
Now what if I only want the user to type http://mydomain/contact then this is not going to work. How would I set it up so the user doesn't have to add http://mydomain/contact/contact
The only way I could find a way around this was to use the match verb.
match "contact" => 'contact#contact'
Does this mean I have to use the match for every page on my site to change the url path?
These are just a few of many question I have that are not so clear in most of the tutorials I have gone over. Please don't tell me to use the user guide as I have already and am felling overwhelmed right now. I just would love some clear answers from some developers who are working in rails and would go about setting up a structure like I have outlined above.
Thanks
You're going to get some conflicting advice I think, but here's what I'd do.
Create a MainController (I prefer HomeController as it will also handle the homepage, but that's just me). This controller will handle the actions for home, about, and contact.
Create a PhotosController since you said photos come from the database and there's a good chance there is an index/listing page and individual pages for each photo.
Create a WorksController that handles the work main page and all the sub pages.
Now.. some people would argue (myself included) that home, about, contact, and all the work pages (sub pages too) should be handled by a generic PagesController that is smart enough to know what to do. I'm not gonna get into that now though.
The difference between these two routes:
get "photos/photos"
resources :photos
Is that the first will only create a single route for a GET request to '/photos/photos'. The second will create the standard CRUD operations for '/photos'.
For your static pages, I probably would go ahead and just create:
match "about" => 'main#about'
match "contact" => 'main#contact'
...
It's harder to say for the photos and work since I don't know what all you'll be doing there. The above isn't as DRY as it could be, but unless you go the "smart pages controller" route it's the simplest.

Twitter Ruby Gem

I am trying to setup the Twitter gem, and I feel like I'm almost there... kind of.
Right now I was trying to follow this link:
http://www.phyowaiwin.com/how-to-download-and-display-twitter-feeds-for-new-year-resolution-using-ruby-on-rails
It is a bit old though, and I guess its instructions are a bit out of date. I have created a twitter model, twitter db migration and a twitter controller(not sure it's needed though), and if i open rails console, and I type:
Twitter.user_timeline("whatever").first.text
It just works. I just can't seem to be able to see it in my view. can you point me in the right direction?
Thanks a lot!
Alex
In your controller that corresponds with your view, you need to assign your results to a variable inside the appropriate functionlike so:
def controller_function
#twitter_data = Twitter.user_timeline("whatever").first.text
end
Then, in your corresponding view you can use the variable
<%= #twitter_data ... %>
Check out http://guides.rubyonrails.org/layouts_and_rendering.html for more guidance on controllers and views

Facebook posting help, adding to facebook whenever a user creates a post

I think this question is a matter of writing nice ruby code, let me see what you guys think. I've already setup all the auth/access token stuff with omniauth and and fbgraph, what I can't seem to work out is how to integrate it when a user creates a post.
My app revolves around users making posts (made up of 'title' and 'content'), I'd like the post to be automatically shared on facebook or twitter or both, depending on the particular authentications the users has setup. And not share anywhere if the user has signed up conventionally without facebook/twitter.
How would I integrate a dynamic way to share the title and content of a user's post whenever they post automatically? I was thinking of some type of after_save to the post model but I can't get it working right. Thank you for any help is it very much appreciated.Also it would great if it was a method that allowed for furture expansion if I wanted to share links and pictures later on.
This is the only post while searching that sheds some light about sharing to both but I'm still confused :(
Easy way of posting on Facebook page (not a profile but a fanpage)
In your Post model have:
after_commit :share_content
def share_content
user.share_content title, content
end
Then in User model have:
def share_content title, content
# some conditionals with whatever stuff you have to determine whether
# it's a twitter and/or facebook update...
if go_for_twitter
twitter.update title
end
if go_for_facebook
facebook.feed! :message => title
# ...etc.
end
end

Resources