how can I get rails_admin to handle associations properly? - ruby-on-rails

Two questions:
1) How can I make a column in the 'list' for a model consist of data from the record's association? In other words, I have a user model and a user has_many posts. I want to simply have a "post count" column in the list. I tried doing:
field :posts do
formatted_value do
value.count
end
end
but that results in a divide by zero error. I even tried doing:
field :posts do
formatted_value do
bindings[:object].posts.count
end
end
but got the same results.
2) How can I filter the listing to a particular scope? For example, I want to make the users post count be a link that is clickable which will show all posts for the given user.
The best I could figure out how to do this was to do:
# note that I created a method post_count to temporarily solve problem #1
field :post_count do
formatted_value do
bindings[:view].link_to value, "/admin/posts?query=#{bindings[:object].id}"
end
end
Which doesn't work very well. Is there a way to instruct rails-admin to do a .where(:user_id => xxx) on the model?
The other thing I wasn't crazy about was having to manually put in 'admin/posts'.. I was trying to see if I could do rails_admin_list_path(:model_name => "posts"). but that didn't seem to work.

You'd probably get a better response on the rails_admin mailing list - http://groups.google.com/group/rails_admin/
For your first question, this should do the trick:
field :posts, :virtual do
formatted_value do
bindings[:object].posts.count
end
end
For your second question, rails_admin now has a filter system - see the "add filter" dropdown at http://demo.railsadmin.org/admin/players . Tapping into that would be a much better method.
rails_admin_list_path(:model_name => "posts") should work, you might have to include Rails.application.routes.url_helpers or similar.

Try adding this to your rails_admin.rb
RailsAdmin.config {|c| c.label_methods << :field_name}
worked for me

Related

Rails - ActiveAdmin - Can't get associated modal attribute to show

I am using ActiveAdmin and have an Account model and a User model. Each account will have a has_many relationship with users, and I'd like to be able to list the user names on the account table.
I've seen quite a few SO questions that address the same question and this is how far I've managed to get:
index do
column :id
column :account_status
column :users do |account|
account.users.each do |user|
auto_link user
end
end
column :address do |account|
account.address
end
column :created_at
column :updated_at
actions
end
Note: i've also tried replacing "auto_link user" with "user.name"
This kind of works. It does get the data, but instead of showing attribute values I seem to just get a memory address reference:
I should say here that I am quite new to both Ruby and Rails, so it is likely that I am just missing the point. Considering what I have, is there something I've missed out?
account.users.each will return an array of User objects. That's why you got something like "a memory address reference". To return a list of user.name, you should do something like this:
column :users do |account|
account.users.pluck(:name).join(', ')
end
I use join here to convert an array of names to a string. I'm not sure without join, what will be displayed. You can try it by yourself :)

List all Items from User by its foreign key

I am using ActiveAdmin and i want to list items which belong to a specific user. The two resources have the has_many and belongs_to relationship.
An index pages is listing all the users. Now i would like to render a show block for each user his items.
My show looks now something like this:
ActiveAdmin.register User do
show do
panel "Specific Item List" do
table_for Item.where("user_id=1").fnidi_each do |i|
column("ID"){|item|item.id}
column("Name"){|item|item.name}
end
end
end
end
How do i inherit the user_id from the page to the show panel ? So that each time show is called i can use the users id for the query.
I know these a basic question but my knowledge of Rails/AA is so far quite basic as well ;) Happy for any advice.
Looking at this code from the ActiveAdmin documentation, where "post" seems to be dynamically generated within the register block suggests that in your case you may be able to just do "user.id", etc.
ActiveAdmin.register Post do
show do
h3 post.title
div do
simple_format post.body
end
end
end
So you might try user.items or Item.where(user_id: user.id) instead of your Item.where("user_id=1").

Updating an ActiveAdmin nested resource using inputs not located on the table

I currently have a form for a nested resource in one of my activeadmin pages:
f.inputs "Courses" do
f.has_many :registrations, :allow_destroy => true, new_record: true do |tc|
tc.input :course
tc.input :semester
end
end
This is for a student resource. A student has many course_offerings through registrations. However, I didn't want users to select the course_offering directly from a menu (Since there will be many repeats of the same course each year). Instead there is an input for course and semester. course and semester are instance variables on the registration model. They are set in the form, then the correct course_offering is found in an after save hook and associated with the registration. The code is as follows:
def semester=(s)
#semester = s.to_i
end
def semester
self.course_offering.semester
end
def course=(co)
#course = co.to_i
end
def course
self.course_offering.course
end
before_save :set_course_offering
def set_course_offering
self.course_offering = CourseOffering.where(semester_id: #semester, course_id: #course).first
#TODO: Handle case where no course offering is found
end
I am having two problems. The first is that I get a nil pointer error when registrations table is empty.
undefined method `course' for nil:NilClass
I have accepts_nested_attributes call in my student model.
accepts_nested_attributes_for :registrations, :allow_destroy => true
which is the only suggestion I get when looking up the error but still get it despite having that piece of code. It seems to work fine when I remove the course and semester and replace it with a course_offering instead.
The next problem I have is that the student record does not save after hitting update. I assume this is because I don't make any changes that write to the database when I only update the two course and semester instance variables only. I either need to update another input or add the call to the semester= method.
You get an undefined method error because when the registration table is empty there are no course offerings associated with your student, so in the accessor method for course you get nil for self.course_offerings. You could try this instead which takes the nil value into account:
def course
self.course_offering.try(:course)
end
You don't need the accept_nested_attributes_for because you don't want to create or modify course offerings through students.
For your second problem: you're right about the dirty tracking. Your model is not saved because your student model has not been modified from the perspective of ActiveRecord. You need to flag an attribute (eg course_offering) as dirty by hand with the course_attribute_will_change! method before saving the model.
Although this situation looks like a good example to introduce form objects. There is a great library for that called reform.

rails_admin edit belongs_to ordering

I'm trying to override the default ordering of the belongs_to drop-downs for the new/edit forms. I'd like to order the belongs_to relationships to name instead of the default id desc.
Based on the wiki (https://github.com/sferik/rails_admin/wiki/Associations-scoping) I have this:
field :theme do
associated_collection_cache_all false
associated_collection_scope do
Proc.new { |scope|
scope = scope.reorder("themes.name ASC")
}
end
end
end
The reorder seems to be ignored while where statements are picked up.
Are you sure the column you're trying to sort by is 'names' and not 'name'?
A good way to debug this would be to open a rails console and see if your reorder actually works this way.
Theme.all.reorder("themes.names ASC")
I'm guessing that probably won't work as expected and you need to tweak the reorder.
If you want to see the SQL it's creating, you can do this.
Theme.all.reorder("themes.names ASC").to_sql
That might give you more information about whats going wrong.

activerecord json output not showing relationship in output

I've got a posts model and of course authors which is a foreign key relationship to my users.
I am trying to output in JSON, the posts with the authors names.
I know this is rails 101, but I can't call post.author because I'm not in a view.
I've tried doing this a few ways, but none seem to be working.
My post model has
belongs_to :user, :foreign_key => :author_id
def post_author
self.each {|a| a['author'] = User.find(a.id)}
end
in my controller I've tried all sorts of
posts=Post.find(:all).includes(:user)
#or
posts=Post.find(:all).includes(:post_author) #don't think this is right anyway, but tried
#and
posts = Post.find(:all)
posts = JSON::Parse(posts.to_json()).merge('author'=>posts.author) #or posts.user, etc etc
of course, none of these have worked, which is why I'm posting here. What's the best way to get the author of a post.
----------------------update ---------------------------
#rjz provided a response which works, but I'm hoping isn't the best way.
He suggested using
posts.to_json(:include=> :user,:only[:username])
this meant I was only getting the username back, but I need more than that so I started using :except instead. The problem here is that I've got a fields like id which I need in the post, but not in the author, but if I exclude them in this manner, the field is excluded from the results completely. I'm also having to list out each field I need, and I'm not sure if that is the best way.
You might have to tease the name of your association a bit to get exactly what you want, but what you're looking for is the :include option when you serialize with to_json:
posts.to_json(:include => :user)

Resources