I have a RoR app with an admin_controller, the admin is able to CRUD Item, now I am a bit confused when it comes to routing. How can I create the app in a way that I can have a link to new_item be like: admin/item/new instead of creating an item controller with a authenticate_admin? method (since I use Device)
All in all how is this kind of routing achieved in rails
e.g. admin/orders/:id
or
store/sales/lates
Ideally , your admin_controller shouldn't do any CURD actions on an Item object. You should use an items_controller for that.
to achieve what you are trying to do, you can use an admin name space and maybe get the item_controller to be inherited from the admin controller.
So, you can have something like,
#app/controllers
AdminController < ApplicationController
end
#app/controllers/admin/
module Admin
ItemsController < AdminController
end
end
#config/routes
namespace :admin do
resources :items
end
rails namespaces
Related
Routing Error ! uninitialized constant AdminController
This appears to me when trying to go to
localhost:3000/admin
I have been searching a lot , but still stuck!
Rails 4.2.4
Ruby 2.2.3
Activeadmin 1.0.0 pre2
My Gem file :5dPDVf http://ideone.com/5dPDVf
My routes.rb File : dF6EFThttp://ideone.com/dF6EFT
Did you run rails generate active_admin:install ?
Looks like you need to create an AdminsController class like this:
in app/controllers/admins_controller.rb
class AdminsController < ApplicationController
def index
end
end
You might want to read Action Controller Overview
You might have it defined as AdminsController (plural) so you might need to adjust your routes to this instead of creating an AdminsController class.
The controller name should be plural (this is a naming convention in Rails).
routes.rb
resources :admins
You'll also need a view file inapp/views/admins/ called index.html.erb
and then visit http://localhost:3000/admins.
I have a controller with several actions. Many follow this pattern:
def favorites
#favorites = Favorite.where(organization_id: #resource.id).page(params[:page]).per(50)
end
It's not just favorites, but there's also downloads, searches, lists etc and they're all so similar that I wanted to create a method that I could call in a before_filter. Something like this:
def set_instance_variable
subject = __method__
class = __method__.singularize.constantize
instance_variable = self.class.instance_variable_set("##{subject}", "#{class}.where(organization_id: #resource.id).page(params[:page]).per(50)")
end
The syntax might be a little off here, but I know this won't work because __method__ will always be set_instance_variable and not the parent method where it is called.
Is there a way to dynamically set instance variables based on the method that defines them? Is this example above even on the right track?
I like the way the CanCan library handles this problem. With CanCan, you call a class method at the top of your controller:
load_resource
CanCan then looks at:
the action you're in to determine whether you want a collection or singular resource,
the name of the controller to determine the class to load
authorization rules to add scopes like your organization_id restriction (cancan is also a library for defining these)
I think pagination and resource loading are separate things, and you shouldn't put them in the same method. I'd shoot for an interface like this:
class FavoritesController
load_resource
paginate_resource only: [:index]
def show
# #favorite loaded here
end
def index
# #favorites loaded and paginated here
end
end
https://github.com/CanCanCommunity/cancancan/blob/develop/lib/cancan/controller_resource.rb#L29
If it makes more sense in your application to have non-restful resources, then you can't re-use the convention-based thing cancan is and instead have to define your own function. Consider something like this:
def favorites
#favorites = load_resource Favorite
end
private
def load_resource(klass)
klass.where(organization_id: #resource.id).page(params[:page]).per(50)
end
I am trying to set up an application where I can route via a String key instead of an id attribute. To illustrate this, please consider the following:
I have a class Foo which inherits from the ActiveRecord::Base and is implemented as follows:
class Foo < ActiveRecord::Base
attr_accessible :subject
Subject is a string type which exists in my database.
I have a controller which I implement as follows:
class SubjectController < ApplicationController
def index
#snip
end
As you can see, the SubjectController inherits from the ApplicationController.
Running rake routes gives me the standard (GET, POST, PUT, DELETE) routes for my subject. This is the expected behavior and I understand this functionality.
I want to know how I can extend the routes.rb file so that I can use a string url in order to access a subject. For example:
Instead of typing in localhost:3000/subject/1, I would like this /:id to resolve when I type in the url: localhost:3000/subject/grumpy-cat-says-hello
What does this implementation look like?
How should I setup my routes.rb file to accommodate this?
How should I configure my application to allow for this type of implementation?
Thank you in advance.
I've always used https://github.com/FriendlyId/friendly_id for this stuff.
If you prefer something simpler, this will do
class Foo < ActiveRecord::Base
def to_param
[id, subject.parameterize].join("-")
end
end
Then you can access your resource with: localhost:3000/foos/1-grumpy-cat-says-hello
Basically, since the name of the resource still starts with a number, it will be converted to a number by Rails and everything will work seamlessly.
This Gist goes in much greater detail about this topic :)
This is probably a stupid question, can you have a function available to multiple controllers?
I have 2 controllers
class C1Controller < ActionController::Base
def add(input_value)
#output_value = input_value * 2
end
end
now I would like to use this add function in another controller like so
class C2Controller < ActionController::Base
#new_value = add(2)
end
Define that function in app/controllers/application_controller.rb, and it will be available in all controllers.
ApplicationController can be used for this.
Make sure your other controllers are derived from ApplicationController and not directly from ActionController, as they should be. Then you can configure filters, common methods etc in the single ApplicationController.
But it might be wise to define a parent controller and have your controllers derive from it, as the ApplicationController is not really meant for random code sharing, but for specific purposes like filters and forgery protection.
You could also define the function in a helper and then include this helper in your ApplicationController. As follows:
include SessionsHelper
Let's say I have a nested resource like in the Rails guide example:
http://guides.rubyonrails.org/routing.html#nested-resources
resources :magazines do
resources :ads
end
This routes a call to /magazines/newsweek/ads to the AdsController#index. It requires a magazine_id in the URL...how should I go about creating a view that is based off of a template used for Ads#index yet also includes the context of the parent resource?
For example, all parent resources that have Ads will have a table list of those ads. But I'd like the top of the view to include boilerplate information for each Magazine. If /magazines/newsweek/ads goes directly to the generic AdsController#index, how do I make that #index view aware of the need to include boilerplate generated from the Magazine model?
And if other models have relationships to ads (TelevisionShow has_many :ads), I'd like AdsController#index to react differently to those as well.
EDIT:
This is how I've done such things in the past, going through MagazinesController. Let's say I want a separate Magazine#show action...the routes would be:
resources :magazines
resources :ads
get "magazines/:id/ads", :controller=>"companies", :action=>"ads"
And the controller would be:
class MagazinesController < ApplicationController
def show
...
end
def ads
...
end
end
And then Magazine#ads would have a partial for ads listings that would be shared across all other types of resources.
Makes sense to me, but that route seems like it could somehow be DRYer?
It sounds like you should be working in the magazine controller.
#Magazine_controller
def show
#magazine = Magazine.find(params[:id])
#ads = #magazine.ads
end
Then in your view just render a partial for your collection of ads. Your ads partial will be saved in the ads area. So in your veiw:
<%= render :partial => "ads/ad", :collection => #ads %>
http://guides.rubyonrails.org/layouts_and_rendering.html#using-partials