how can I hide resources? - sql

I want to create a page where it shows the resource created by other users but hide the resources created by current_user. is there a method or certain way in which I can do so?
class ExamplesController < ApplicationController
def index
#examples = Example.all.order("created_at DESC")
#creator_examples = Example.where(creator: current_user).order("created_at DESC") <---hide this!!!
end

You can simply manipulate your where clause into something like this:
def index
#examples = Example.all.order("created_at DESC")
#creator_examples = #examples.where.not(id: current_user.id)
end
This is for rails 4, if you're using rails 3
#creator_examples = Example.where("id != ?", current_user.id)
Note -> Example.all in rails 3 returns an array so you can't chain it with where

Related

Restrict user role from accessing through url using pundit

I am working on roles and permissions in my application. For this I am using pundit gem. As per the requirement the client_admin role can view users from tested_by column drop down as listed in the below view file but should not be able to access users/ index page.
app/views/project_issues/_form.slim:
.padded.user-config
- unless #project_issue.errors.empty?
.alert.alert-danger
= #project_issue.errors.full_messages.join('. ') + '.'
= simple_form_for #project_issue do |f|
= f.input :reference_number
= f.input :tested_by,
as: :select2,
path: users_path(format: :json, roles: [:super_admin, :client_admin]),
prompt: 'Select a User',
attribute_method: :tested_by
app/policies/project_issue_policy.rb:
def new?
user.is?(:super_admin, :client_admin)
end
app/models/project_issue.rb:
class ProjectIssue < ApplicationRecord
belongs_to :tested_by, class_name: 'User'
end
user_policy.rb:
def index?
user.is?(:sales_user, :sales_manager, :super_admin, :client_admin)
end
As per the above code the users can still be accessed to index page via url. Can we add any scope or method? Please help.
I am writing this answer based on the fact that my assumption from the comments is correct.
Define a scope in your policy.
user_policy.rb
class UserPolicy < ApplicationPolicy
def index?
user.is?(:sales_user, :sales_manager, :super_admin, :client_admin)
end
...
class Scope < Scope
def resolve
if user.is?(:client_admin)
User.where.not(tested_by_id: nil) # Or something like that.
elsif user.is?(:sales_user, :sales_manager, :super_admin)
User.where(tested_by_id: nil) # Iam still not sure on what you differentiate your users ;).
else
User.none
end
end
end
end
You can "access" your scope in your controllers like so:
users_controller.rb
class UsersController < ApplicationController
def index
authorize User
#users = policy_scope(User)
end
...
end

is there any way that can offset from specific record when using scope

i have a lot of methods that look for records after specific active record. examples are:
def photo_recent
offsetphoto = Photo.find(params[:id])
#photos = Photo.recent.where('created_at> ?', offsetphoto.id).limit(10)#recent is a scope using created_at
end
def photo_recent
offsetphoto = Photo.find(params[:id])
#photos = Photo.popular.where('like_count > ?', offsetphoto.like_count).limit(10)#popular is a scope using like_count
end
i was wondering if there is any way to modularize this such as:
#photos = Photo.recent.offset(Photo.find(params[:id])).limit(10)
# models/photo.rb
scope :most_recent_starting_from, -> (photo) { order(created_at: :asc).where('created_at >= ?', photo.created_at) }
Example Usage
photo = Photo.find(123)
ten_next_created_photos_after_photo = Photo.most_recent_starting_from(photo).limit(10)
You could write a scope that just takes everything from the current Photo
scope :offset_from, -> (photo) { where('id >= ?', photo.id) }
Photo.offset_from(Photo.find(params[:id]))......

undefined method `order' for []:Array

I have the following code where I load the activities for the user based on whether or not they are an admin. Users can only see their own activity feed, whereas admins can see the entire stream. This is a precursor to sharing activity feeds with friends, etc.
def index
if current_user?
#incidents = Incident.find_all_by_user_id(current_user.id).order("created_at desc")
else
#incidents = Incident.all.order("created_at desc")
end
end
I am getting the above referenced error(undefined method "order" for []:Array). It seems to be the .order reference, but I have checked the rails Guides and it seems to be correct syntax.
Any ideas?
Try changing the find_by... to where, so:
def index
if current_user?
#incidents = Incident.where(user_id: current_user.id).order("created_at desc")
else
#incidents = Incident.all.order("created_at desc")
end
end
should work :-)
The #index action method can be simplified and optimized (by replacement find_all_by with where) to:
def index
clause = current_user? && Incident.where(user_id: current_user.id) || Incident
#incidents = clause.order("created_at desc")
end

Devise Gem and the Geocoder Gem

I am using geocoder and the devise gem. And i am trying to get coupons near user's location
Coupon Model
def index
if params[:search].present?
#coupons = Coupon.near([user_long, user_lat], 50, :order => :distance)
else
#coupons = Coupon.all
end
end
Application Helper
I have defined the user_long and user_lat
def user_long
current_user.longitude
end
def user_lat
current_user.latitude
end
Devise Gem
I have tried to use the devise gem helper to get the values like so
Coupon Model
def index
if params[:search].present?
#coupons = Coupon.near([current_user.longitude, current_user.latitude], 50, :order => :distance)
else
#coupons = Coupon.all
end
end
I am hitting the walls and celling with this. Can someone help out, i know this is newbie question for but i can't solve it so save my life?
You are not seeing anything on the index page because your #coupons array is empty:
#coupons = Coupon.near([current_user.longitude, current_user.latitude], 50, :order => :distance)
In development log (in the same window where rails server is running, if you are running the rails server from console), you should check out the SQL query generated for CouponsController#index action.
Assuming you defined your 'near' query like this:
class Coupon
scope :near, lambda { |longitude, latitude| some logic...
end
You can debug this 'near' method using "rails console" like this:
rails console
> Coupon.near(10, 20)
etc..
My mistake was that i that i had the longitude before that latitude, It was taking away the logic
This works.
def index
#coupons = Coupon.near([current_user.latitude, current_user.longitude], 50, :order => :distance)
end

override to_xml to limit fields returned

using ruby 1.9.2 and rails 3, i would like to limit the fields returned when a record is accessed as json or xml (the only two formats allowed).
this very useful post introduced me to respond_with and i found somewhere online that a nice way to blanket allow/deny some fields is to override as_json or to_xml for the class and set :only or :except to limit fields.
example:
class Widget < ActiveRecord::Base
def as_json(options={})
super(:except => [:created_at, :updated_at])
end
def to_xml(options={})
super(:except => [:created_at, :updated_at])
end
end
class WidgetsController < ApplicationController
respond_to :json, :xml
def index
respond_with(#widgets = Widgets.all)
end
def show
respond_with(#widget = Widget.find(params[:id]))
end
end
this is exactly what i am looking for and works for json, but for xml "index" (GET /widgets.xml) it responds with an empty Widget array. if i remove the to_xml override i get the expected results. am i doing something wrong, and/or why does the Widgets.to_xml override affect the Array.to_xml result?
i can work around this by using
respond_with(#widgets = Widgets.all, :except => [:created_at, :updated_at])
but do not feel that is a very DRY method.
In your to_xml method, do the following:
def to_xml(options={})
options.merge!(:except => [:created_at, :updated_at])
super(options)
end
That should fix you up.