Ruby on Rails - Active Admin: Conflict with a Global Variable - ruby-on-rails

On Rails 4 with the latest version of Active Admin (using Ransack). I have an Award model that I made available globally in my application_controller.rb:
before_action :set_awards
private
def set_awards
#awards = Award.all
end
This is so I could have a global navigation dropdown listing all awards (on the public side). I think this is conflicting with Active Admin. When I went to the Awards index page, I got the following error message:
Collection is not a paginated scope. Set collection.page(params[:page]).per(10) before calling :paginated_collection.
I am not sure what this means exactly but since this is the only model this happens to, I'm guessing it has something to do with my code in the app controller. I think my problem is similar to this question:
Rails 3.2 ActiveAdmin 'Collection is not a paginated scope.' error
...I would prefer not to change the model's label and the metasearch code provided doesn't work because (I think) Active Admin now uses Ransack. Thanks for any help.

I have had the same problem and it was a variable name i was declaring at the application controller that was conflicting with the ActiveAdmin.
I have a model called Post and in my applicationController i had a method like this:
def load_posts
#posts = Post.all
end
It returned me the error you mention, so i fixed it changing the variable name to:
def load_posts
#post_list = Post.all
end
Hope it helps.

May be you overwrited a local variable #awards in ApplicationController, but Active Admins is inheriting from the application controller.
Just rename your variable and it will run.

Related

How to get the path for a collection in ActiveAdmin

I made custom index view for ActiveAdmin, and I would need to get the admin path for the given collection.
Here is what I have:
module ActiveAdmin
module Views
class IndexAsSpecial < ::ActiveAdmin::Component
def build(page_presenter, collection)
//...
// should be something like /admin/posts
path_to_collection = ???
//...
end
def self.index_name
"special"
end
end
I have searched and tried, but all I found is paths for a resource, not for the collection (e.g. resource.route_collection_path )
I also found this, but here I am still missing the right parameters, or maybe the class name of the active admin collection:
Rails.application.routes.url_helpers.polymorphic_path([:admin,:posts])
Just that I need to replace :posts somehow dynamically.
Any ideas?
I must say, that the documentation of ActiveAdmin is very vague here, but after debugging a bit more I found the answer to my question:
helpers.collection_path # will generate /admin/posts
or if you need a member action on the collection:
helpers.resource_path(:action_name) # will generate /admin/posts/action_name

Accessing model in controller equals nil

I've got the following problem
I have a model called Article, which I access at two points.
First at the "home-page ( root )" I just do Article.all and list all of them.
That works fine for me, but whenever I access Article.all on my admin-panel ( /admin/articles ) it just says the following:
My controller looks like this:
def index
#news = Article.all
end
My model can be accessed easily in the rails console:
All of this is somehow solved by opening the controller and just re-saving it.
After a rails restart or logout and login on the site it is broken again
You may wish to organize groups of controllers under a namespace. Most commonly, you might group a number of administrative controllers under an
Admin:: namespace.
At the console:
namespace :admin do
resources :articles
end
This will create a number of routes for each of the articles
use one of the routes to access your controller from Admin
Try converting to array,
#news.to_a.count

Rails: activeadmin overriding create action

I have an activeadmin resource which has a belongs_to :user relationship.
When I create a new Instance of the model in active admin, I want to associate the currently logged in user as the user who created the instance (pretty standard stuff I'd imagine).
So... I got it working with:
controller do
def create
#item = Item.new(params[:item])
#item.user = current_curator
super
end
end
However ;) I'm just wondering how this works? I just hoped that assigning the #item variable the user and then calling super would work (and it does). I also started looking through the gem but couldn't see how it was actually working.
Any pointers would be great. I'm assuming this is something that InheritedResources gives you?
Thanks!
I ran into a similar situation where I didn't really need to completely override the create method. I really only wanted to inject properties before save, and only on create; very similar to your example. After reading through the ActiveAdmin source, I determined that I could use before_create to do what I needed:
ActiveAdmin.register Product do
before_create do |product|
product.creator = current_user
end
end
Another option:
def create
params[:item].merge!({ user_id: current_curator.id })
create!
end
You are right active admin use InheritedResources, all other tools you can see on the end of the page.
As per the AA source code this worked for me:
controller do
def call_before_create(offer)
end
end

ruby on rails should i query to db from controller

I am just getting started with Ruby on Rails and i am not sure how i should do the queries to database in order to get data, add data or edit data...
Is it better to find for example a user from the controller or its better to add the queries into the model?
currently, my user homepage controller looks like this with some simple functionality
class HomeController < ApplicationController
#get current_user variable
helper_method :current_user
def index
if user_signed_in?
#user = User.find_by_id(current_user.id)
else
render_404
end
end
end
it simply checks if the user is logged in and finds the user...
Should i move the db calls to a model for best practice or using the above method is also fine?
The way you did it is fine in my opinion. The controller's job is to set the data for the view and part of setting the data is fetching it from the DB.
For more complex DB query you could use scope which are located in the model. This way the controller does not hold too much logic of DB queries on the model.
You usually want to use a repository pattern which rails gives us by default with active record. I'd say that's perfectly fine. If you had more complex business logic or were pulling from multiple tables, then I'd probably move it into it's own class.

Permalinks with Ruby on Rails (dynamic routes)

I am currently developing a blogging system with Ruby on Rails and want the user to define his "permalinks" for static pages or blog posts, meaning:
the user should be able to set the page name, eg. "test-article" (that should be available via /posts/test-article) - how would I realize this in the rails applications and the routing file?
for user-friendly permalinks you can use gem 'has_permalink'. For more details http://haspermalink.org
Modifying the to_param method in the Model indeed is required/convenient, like the others said already:
def to_param
pagename.parameterize
end
But in order to find the posts you also need to change the Controller, since the default Post.find methods searches for ID and not pagename. For the show action you'd need something like this:
def show
#post = Post.where(:pagename => params[:id]).first
end
Same goes for the other action methods.
You routing rules can stay the same as for regular routes with an ID number.
I personally prefer to do it this way:
Put the following in your Post model (stick it at the bottom before the closing 'end' tag)
def to_param
permalink
end
def permalink
"#{id}-#{title.parameterize}"
end
That's it. You don't need to change any of the find_by methods. This gives you URL's of the form "123-title-of-post".
You can use the friendly_id gem. There are no special controller changes required. Simple add an attribute for example slug to your model..for more details check out the github repo of the gem.
The #63 and #117 episodes of railscasts might help you. Also check out the resources there.
You should have seolink or permalink attribute in pages' or posts' objects. Then you'd just use to_param method for your post or page model that would return that attribute.
to_param method is used in *_path methods when you pass them an object.
So if your post has title "foo bar" and seolink "baz-quux", you define a to_param method in model like this:
def to_param
seolink
end
Then when you do something like post_path(#post) you'll get the /posts/baz-quux or any other relevant url that you have configured in config/routes.rb file (my example applies to resourceful urls). In the show action of your controller you'll just have to find_by_seolink instead of find[_by_id].

Resources