how would one put everything in app/presenters under Presenters namespace?
so app/presenters/admin/article.rb containing
module Presenters
module Admin
class Article
end
end
end
may be available as Presenters::Admin::Article ?
Here's the working answer:
app/presenters/admin/article.rb
module Admin
class Article
end
end
access like: Admin::Article.new
I'm trying to create a back-end area to my application, so I've created a folder named backend and backend_controller.rb inside it. I need the folder because the backend area will have multiple folders, so it's better-separated from my others.
my routes.rb looks like:
namespace :backend do
get 'index'
end
my backend_controller.rb:
class BackendController < ApplicationController
def index
end
end
But in this mode Rails will search for my backend_controller.rb inside the controllers folder, not in controller>backend. I've tried many variations, and I get routing errors.
So what is correct way to do that? To set the path /backend to index action instead of /backend/index?
Thanks
What i've done:
based on all answers, principally the one from Cyril DD
I've created the backend_controller.rb on the app/controller folder and in the sub-folder app/controller/backend i created the static_pages_controller.rb and all files looks like this:
app/controllers/backend_controller.rb:
class BackendController < ApplicationController
end
app/controller/backend/static_pages_contter.rb:
class Backend::StaticPagesController < BackendController
def dashboard
end
end
routes.rb:
namespace :backend do
resource :static_pages, path: '', only: [] do
root to:'static_pages#dashboard'
end
this works fine, but cause i'm newbie on rails i must ask. This is a good or a conventional way to do that? to administrate the permissions which user can see on the backend i use the backend_controller.rb right? and at last wy i must use resource: instead just get ''
Answering your question
Alright, namespace :something is a shorthand for scope 'something', module: 'something', as: 'something'
Now your declaration is very ambiguous, because you don't specify a controller. Typical declarations look like (assume you have a controller controllers/backend/some_resources_controller.rb and you want to generate default routes)
namespace :backend do
resources :some_resources
end
Now what you did
namespace :backend
get 'index'
end
is really ambiguous and I'm not surprised it doesn't do what you want. Basically you just tell rails to "look inside subfolder 'backend' and define the route 'index'". oO ? Which file/controller are we even talking about ?
What is your backend_controller.rb supposed to do ? Is it some kind of Control Panel ? Dashboard ? If so you're probably gonna have a lot of non-CRUD actions, but anyways you should go for the following syntax
namespace :backend
# Below line of code will auto-generate the `index` for /backend/backend_controller
resource :backend, only: [:index], path: '' do # we need " path: '' " otherwise we'll have https://xxx/backend/backend/dashboard
# If you have non-CRUD actions, put them here !
get 'dashboard' # https://xxx/backend/dashboard
...
end
# However, this will create URLs like "https://xxx/backend/dashboard", etc.
# If you want to redirect https://xxx/backend/ to your backend_controller#index, use root
root to: 'backend#index' # https://xxx/backend/
end
Last thing as mentionned by other guys, when you namespace a file like your Backend_controller inside /backend/ subfolder, you must rename the class like (/controllers/backend/backend_controller)
class Backend::BackendController < ApplicationController
Remark : if you only have like one or two controller actions, instead of using the resource method, you can declare singular resources
namespace :backend do
root to: 'backend#dashboard'
get 'dashboard', to: 'backend#dashboard' # singular resource
end
An Example of what you may actually really want to do...
I'm not sure you are clear yourself about what you want to do. As an example, here is my architecture
Files
/controllers/application_controller.rb
/controllers/backend_controller.rb
/controllers/backend/static_pages_controller.rb
/controllers/backend/***.rb
The class /controllers/backend_controller.rb will not serve any action, but will override ApplicationController to tune it for backend access (but maybe you don't need to do so)
class BackendController < ApplicationController
# Do you need to change user_access method ? Or any other backend-wide config ?
# If so put this config here, otherwise leave empty
end
Now for every file that goes in the /backend/ subfolder, I inherit the backend_controller
class Backend::StaticPagesController < BackendController
def index
end
# Note : if your index is some kind of dashboard, instead I would declare
def dashboard
end
end
class Backend::SomeResourcesController < BackendController
...
end
Routes
namespace :backend do
root to 'static_pages#index' # https://xxxx/backend/
resource :static_pages, only: [:index], path: '' # https://xxxx/backend/index
resources :some_resources
end
If you choose the dashboard solution in your controller, write instead :
namespace :backend do
root to: static_pages#dashboard # https://xxxx/backend/
resource :static_pages, path: '', only: [] do
get 'dashboard' # https://xxxx/backend/dashboard
end
resources :some_resources
end
Then it's simply
# routes.rb
Rails.application.routes.draw do
namespace :backend, shallow: true do
resource :backend, path:''
end
end
Then in your app/controllers/backend/backend_controller.rb, it'd look like this.
class Backend::BackendController < ApplicationController
def index
end
end
When I use rake routes it shows
Prefix Verb URI Pattern Controller#Action
backend_backends GET /backend(.:format) backend/backends#index
Hope this helps.
I'm looking to chain an additional query onto a scope in a model. The scope is defined in a concern.
module Companyable
extend ActiveSupport::Concern
included do
scope :for_company, ->(id) {
where(:company_id => id)
}
end
end
class Order < ActiveRecord::Base
include Companyable
# I'd like to be able to do something like this:
scope :for_company, ->(id) {
super(id).where.not(:status => 'cancelled')
}
end
However, that understandably throws a NameError: undefined method 'for_company' for class 'Order'
Here's the solution I came up with in my case:
Rather than scope, just go with a regular class method since scope is just "syntactic sugar" for a class method. This is easier to deal with when you need to override using super. In your case it would look like this:
module Companyable
extend ActiveSupport::Concern
module ClassMethods
def for_company(id)
where(:company_id => id)
end
end
end
class Order < ActiveRecord::Base
include Companyable
def self.for_company(id)
super(id).where.not(:status => 'cancelled')
end
end
I have a Rails engine that has no models of its own; just controllers, views, and observers that add functionality to the primary application.
I'm attempting to create an observer but can not get Rails to notice it's existence -- the after_create actions and debug statements in the observer are ignored and inserting syntax errors into the file does not raise an error on startup or when insert a row in the observed table.
I've tried all of the techniques mentioned here with no effect.
#/engines/loansengine/lib/loansengine/engine.rb
module Loansengine
class Engine < ::Rails::Engine
isolate_namespace Loansengine
# OBSERVERS
config.active_record.observers = ['Loansengine::TourObserver']
end
end
Observer:
#/engines/loansengine/observers/loansengine/tour_observer.rb
class Loansengine::TourObserver < ActiveRecord::Observer
observe :tours
def after_create(tour)
test_observer(tour)
end
private
def test_observer(tour)
tour.agent_comments = 'pink'
tour.save
end
end
Think I've figured this out:
module Loansengine
class Engine < ::Rails::Engine
isolate_namespace Loansengine
config.before_initialize do
config.active_record.observers << 'Loansengine::TourObserver'
end
end
end
I've notice the new features of concern in rails4, and I read the document of it in http://edgeapi.rubyonrails.org/classes/ActiveSupport/Concern.html.
But it seems doesn't work as I expect. Here is my code of my /models/concerns/current_user.rb.
require 'active_support/concern'
module CurrentUser
extend ActiveSupport::Concern
module ClassMethods
def accessor_current_user
attr_accessor :current_user
end
end
end
class ActiveRecord::Base
include CurrentUser
end
You probably notice that last 3 lines of my code, that's because I want all my models can call the method and I think it may be a good way to achieve that. But when i start rails server, it just cannot call the accessor_current_user method. So I am confusing about this. I really don't know the reason. Hope someone can help me. :)
Update!
Finally, i found it's maybe a good way to create a ActiveRecord::Base class in the initializers fold, and then include the CurrentUser in the class.
Try:
require 'active_support/concern'
module CurrentUser
extend ActiveSupport::Concern
included do
attr_accessor :current_user
end
module ClassMethods
end
end
class ActiveRecord::Base
include CurrentUser
end
Then you should be able to do something like this:
foo = Foo.new
foo.current_user
Where Foo is:
class Foo < ActiveRecord:Base
include CurrentUser
end
The way you are calling accessor_current_user is wrong. This way you can call ActiveRecord::Base.accessor_current_user method and it will execute the code without any error. And then you can call
ar = ActiveRecord::Base.new
ar.current_user = "foo"
ar.current_user # this will return 'foo'
But the correct way to implement the attr_accessor using ActiveSupport::Concern is
module CurrentUser
extend ActiveSupport::Concern
included do
attr_accessor :current_user
end
end
If you are writing your code in rails, then you don't need require 'active_support/concern'. Please refer http://blog.neerajk.com/articles/2014-11-26-is-active-support-concern-really-another-concern/