Using Ability class in Rails Engine - ruby

I have a engine inside the lib folder named Support. In that folder, I have a Ticket controller.
I have created an ability class in the main app and I'm trying to manage all the models for the admin role. When I call the Tickets controller, it throws the error:
NameError in Support::TicketsController#index uninitialized constant Ticket
The app/model/ability.rb file is:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
if user.role? == :admin
can :manage , :all
end
end
end
The lib/support/tickets_controller.rb file is:
module Support
class TicketsController < Support::ApplicationController
load_and_authorize_resource
respond_to :html, :xml, :json
def index
end
end
end

If the model class is namespaced differently than the controller, you will need to specify the :class option.
module Support
class TicketsController < ApplicationController
load_and_authorize_resource :class => Support::Ticket
end
end

Related

Paperclip don't save on database

I am using the following Gems:
'paperclip'
'aws-sdk', '~> 2.3'
I would like to save images to S3, but am unable to get them to save.
model/user.rb
class User < ApplicationRecord
# This method associates the attribute ":avatar" with a file attachment
has_attached_file :avatar, styles: {
thumb: '100x100>',
square: '200x200#',
medium: '300x300>'
}
# Validate the attached image is image/jpg, image/png, etc
validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
end
migration
class AddAvatarToUsers < ActiveRecord::Migration[5.1]
def self.up
add_attachment :users, :avatar
end
def self.down
remove_attachment :users, :avatar
end
end
controllers/users_controller.rb
class UsersController < ApplicationController
def edit
#user = User.find_by(id: params[:id])
end
def update
#user = User.find(params[:id])
if #user.update(user_params)
flash[:notice] = "Edit successfully"
redirect_to("/users/#{#user.id}")
end
end
private
def user_params
params.require(:user).permit(:avatar, :name, :email, :phone_number, :description, :college_name)
end
end
Why is the image avatar not being stored in the database?
Should I add any database columns? What should I do? I would appreciate any input to help me solve this problem.
Paperclip must be configured to use S3 to store the objects (images). It will store metadata associated with these in the database, but not the images.
See Paperclip Documentation
You will also need to set an access policy for your S3 bucket, and define on the User model how they are to be addressed from S3.

How to access 'layout' of parent controller?

In one of my controllers I want to change the layout given some condition, and otherwise keep the default layout used by the parent ApplicationController (was "application" initially, but I'm trying some others now). Tried accessing the "layout" using alias_method but it doesn't seem to work. My code:
class SomeController < ApplicationController
alias_method :parent_layout, :layout
layout :some_layout
def some_layout
if some_condition
"new_layout"
else
:parent_layout
end
end
end
This gives an error:
ActionController::RoutingError (undefined method `layout' for class `SomeController'):
app/controllers/some_controller.rb:6:in `alias_method'
app/controllers/some_controller.rb:6:in `<class:SomeController>'
app/controllers/some_controller.rb:3:in `<top (required)>'
It looks like you have a bunch of options. Check out the docs here (search for "finding layouts")
http://guides.rubyonrails.org/layouts_and_rendering.html
Some possibilities, depending on just how complex you need it to be:
# Proc-based
class ProductsController < ApplicationController
layout Proc.new { |controller| controller.request.xhr? ? "popup" : "application" }
end
# Route based, :except and :only
class ProductsController < ApplicationController
layout "product", except: [:index, :rss]
end
# Method-based
class OldArticlesController < SpecialArticlesController
layout false
def show
#article = Article.find(params[:id])
end
def index
#old_articles = Article.older
render layout: "old"
end
# ...
end
I'm not sure how your code is structured but it looks like the first could work for you:
class SomeController < ApplicationController
layout Proc.new { |controller| controller.some_condition? ? "new_layout" : "application" }
end

How to access ActiveModel attributes from a method call on the class?

I need to reference user#role to define an association in a module. I've tried with a block as shown below, but that doesn't work. How does Rails implement behavior like this?
class User < ActiveRecord::Base
include Profile
has_profile { |user| { class_name: "#{user.role}::Profile" }}
end
module Profile
extend ActiveSupport::Concern
module ClassMethods
def has_profile(&block)
role = ### How to access #role ? ###
class_eval do
has_one :profile, class_name: "#{role}::Profile"
end
...
You might need to do something like this. I didn't tested and I'm just supposing you can do this kind of stuff
class User < ActiveRecord::Base
include Profile
has_profile { |user| user.role }
end
module Profile
extend ActiveSupport::Concern
included do
after_initialize :_init_profile
end
def _init_profile
role = #_role_block.call(self)
# Here we do class eval on singleton so we dont change base class
# I'm not sure if this works as it is but should be close enought
class << self; self; end.class_eval do
has_one :profile, class_name: "#{role}::Profile"
end
end
module ClassMethods
def has_profile(&block)
#_role_block = block
...
This works:
module Models
module Profile
extend ActiveSupport::Concern
included do
after_initialize :_init_profile
end
module ClassMethods
def has_profile(&block)
#profile_association_block = block
end
end
def _init_profile
block = self.class.instance_variable_get :#profile_association_block
self.class.has_one :profile, block.call(self)
end

ActiveModel::MassAssignmentSecurity::Error in ApiUsersController#create

I am not able to create new api_user. Everytime I try to create it I get
Can't mass-assign protected attributes: utf8, authenticity_token, api_user, commit, action, controller
here's my model api_user.rb
class ApiUser < ActiveRecord::Base
attr_accessible :api_key, :count, :email, :name, :organization
end
controller api_users_controller.rb
class ApiUsersController < ApplicationController
#skip_before_filter :verify_authenticity_token
def new
#api_user = ApiUser.new
end
def create
#api_user=ApiUser.create(params)
render :text=>"#{#api_user.id}"
end
def destroy
#api_user=ApiUser.find(params[:id])
#api_user.destroy
render :text=>"Deleted successfully"
end
end
I am using Ruby 1.9.2 and Rails 3.2.3
In order to create the ApiUser, you should use only the correct params:
#api_user=ApiUser.create(params[:api_user])
not all the paramshash

Confusing about a function :before_filter

I have following controller:
class CarsController < ApplicationController
autocomplete :user, :name
before_filter :require_user, :except => [:my_action]
def index
end
...
def my_action
end
end
I want to allow to see all actions in this controller only for log in users - this works me fine. But the action my_action I would like to have accesible for everyone - also for a people who are not log in.
I tried to set :before_filter with the :except parameter, also with the :only parameter, but nothing works me... The app always want for me to be log in... what I am doing still wrong?
EDIT: require_user from application_controller.rb:
def require_no_user
logger.debug "ApplicationController::require_no_user"
if current_user
#store_location
flash[:warning] = "You must be logged out to access this page"
redirect_to account_url
return false
end
end
Use
skip_before_filter :require_user, :only => [:my_action]

Resources