I have a model Order. In the index, I want the current_user to see the index with only their orders. Order belongs_to :admin_user. AdminUser has_many :orders. I am using activeadmin in my app, if that makes a difference. I am getting this error:
Couldn't find Order without an ID
The line giving the error is the second line in my order controller.(redacted unnecessary info)
index do
#order = Order.where(admin_user_id: current_admin_user.id, order_id: resource.id)
column "ID" do |order|
link_to order.id, admin_order_path(order)
end
column "Proof" do |order|
image_tag order.proof_url(:proof).to_s
end
column "Name" do |order|
link_to order.name, admin_order_path(order)
end
column(:customer, :sortable => :customer_id)
column "Category", :order_category
column "Status", :order_status
column "Priority", :order_priority
column "Due Date", :end_date
default_actions
end
here is my order model requested by #jamesw
class Order < ActiveRecord::Base
attr_accessible :color_back, :color_front, :color_sleeve, :end_date, :name, :start_date, :whiteboard, :customer_id, :order_category_id, :order_type_id, :order_status_id, :order_priority_id, :print_location_id, :artwork, :proof, :line_items_attributes, :assignee_id, :admin_user_id
mount_uploader :artwork, ArtworkUploader
mount_uploader :proof, ProofUploader
has_many :line_items
belongs_to :assignee, :class_name => "AdminUser"
belongs_to :customer
belongs_to :order_category
belongs_to :order_type
belongs_to :order_status
belongs_to :order_priority
belongs_to :print_location
belongs_to :admin_user
accepts_nested_attributes_for :line_items, :allow_destroy => true
scope :owned_by, lambda { |user| includes(:assignee).where("admin_users.id = ?", user.id) }
def default_values
if new_record?
self.start_date ||= Date.today
self.number ||= (Order.maximum(:number) + 1 rescue 1)
end
end
end
It looks like you're trying to filter the Orders table by order_id. Unless you've built your DB in a non-standard manner, the ID field of the orders table would typically be id (not order_id).
That issue aside, I doubt you want to be passing in an order id for the index action since that would only return a single record, and by it's nature the index action should list many records (in your case, all records for the current_admin_user).
If neither of those issues solve your problem, try commenting out the lines 1 by 1.
Try to add this controller method
ActiveAdmin.register Order do
controller do
def scoped_collection
Order.where(:admin_user => current_admin_user.id)
end
end
end
see more here:
Two pages for the same resource - ActiveAdmin
I fixed the issue by taking the line in question out and using scope_to :current_user. I am wondering though, how to add a conditional statement to still allow the admin to view this? here is a look at the controller now.
scope_to current_user
index do
column "ID" do |order|
link_to order.id, admin_order_path(order)
end
column "Proof" do |order|
image_tag order.proof_url(:proof).to_s
end
column "Name" do |order|
link_to order.name, admin_order_path(order)
end
column(:customer, :sortable => :customer_id)
column "Category", :order_category
column "Status", :order_status
column "Priority", :order_priority
column "Due Date", :end_date
default_actions
end
Related
I'm trying to filter a list of Products based on 2 tags,
class Product < ActiveRecord::Base
has_many :tags
end
class Tag < ActiveRecord::Base {
:id => :integer,
:created_at => :datetime,
:updated_at => :datetime,
:key => :string
}
How can I format a query statement that allows me to find a product which has 2 tags, one with key 'fragile', and one with key 'perishable'?
Product.joins(:tags).where("tags.key IN (?)", ['fragile', 'perishable']).group('products.id').having('COUNT(tags.id) = ?', 2)
I have a model names TeamInvite that I am trying to create a team_invite_params method for.
When I created the migration for the table, because I wanted to keep track of the sender and recipient, I opted for the custom field names
sender_id
and
recipient_id
to not mix up which user was which.
Anyway, when I try and permit the parameters for a team_invite, I am having trouble telling the permit method that the
Edit:
"team_invite"=>{"user"=>"2"}
is in fact what should go under recipient_id. All the methods I have tried either don't work or end up passing no value at all.
Controller
def create
#team_invite = TeamInvite.new(team_invite_params)
end
Model
class TeamInvite < ApplicationRecord
belongs_to :recipient, class_name: "User"
belongs_to :sender, class_name: "User"
end
Params:
{"utf8"=>"✓", "authenticity_token"=>"0QLA9YiTu9nAf6QJLX5rg0DWa7CAMjqGOlUBICbcL8Ucs2DsCDgGBnhiDXPa/ot8DK0xwTR1D7MASu4/9tVj0w==", "team_invite"=>{"recipient_id"=>"2"}, "commit"=>"Save Team invite"}
View (if it matters):
<%= form_for :team_invite, url: team_invites_path do |f| %>
<%= f.select :recipient_id, User.all.collect { |p| [ p.name, p.id ] }, include_blank: false %>
<%= f.submit %>
<% end %>
Migration:
class CreateTeamInvite < ActiveRecord::Migration[5.0]
def change
create_table :team_invites do |t|
t.references :team, foreign_key: true
t.integer :recipient_id
t.integer :sender_id
t.timestamps
end
end
end
You need:
params.permit(:team_invites => [ :user ]) #or whatever other nested team_invite params you want to pass in.
Docs for strong_params here: https://github.com/rails/strong_parameters
ActiveAdmin.register User do
index do
column :email
column :first_name
column :surname
end
end
app/models/user.rb
has_many :tasks
app/models/task.rb
belongs_to :user
I have all the attributes in the User model. Is it possible to call those attributes in the Task model. I tried to look up for it but couldn't find anything suitable. For example:
ActiveAdmin.register Task do
index do
column :email
column :first_name
column :surname
end
end
Yes, you can! For example:
ActiveAdmin.register Task do
index do
column "Email" do |task|
task.user.email
end
column "First name" do |task|
task.user.first_name
end
end
end
We're using ActiveAdmin for our admin view, here's the current index code. The Book model retrieves data from a single "books" postgres table :
class Book < ActiveRecord::Base
has_many :stories, class_name: "BookStory"
...
ActiveAdmin.register Book do
index do
column :id
column :title
column :subtitle
column :isbn_13
default_actions
end
...
I would like to add a "stories" column in our index view. A "story" is an action from an user, associated with a book. The stories are stored in a "book_stories" table.
class BookStory < ActiveRecord::Base
belongs_to :user,
belongs_to :book,
From a SQL point of view, this is how I would like to implement the query into ActiveAdmin. This query gives me the wanted result into pgAdmin3 :
SELECT books.id,books.title,books.subtitle,books.isbn_13,COUNT(book_stories.book_id) AS count
FROM books
INNER JOIN book_stories ON books.id = book_stories.book_id
GROUP BY books.id
ORDER BY count DESC
LIMIT 30;
And I really don't know how to implement a sortable "Stories" column into our admin view. By sortable, I mean, being able to sort the book like by their stories count. I managed to show the stories count per book with this code, but the column isn't sortable :
ActiveAdmin.register Book do
index do
column :id
column :title
column :subtitle
column :isbn_13
column :stories do |book|
BookStory.joins(:book).group.where("books.id = #{book.id}").count
default_actions
end
...
Any ideas ?
Take a look on the belongs_to counter_cache option. http://guides.rubyonrails.org/association_basics.html#counter-cache
class BookStory < ActiveRecord::Base
belongs_to :book, counter_cache: true
end
ActiveAdmin.register Book do
index do
column :id
column :title
column :subtitle
column :isbn_13
column :book_stories_count # will be sortable by default
default_actions
end
end
Okay, it's working. Thank you very much ! Here's my code :
Book model :
class Book < ActiveRecord::Base
has_many :stories, class_name: "BookStory"
Book stories model :
class BookStory < ActiveRecord::Base
belongs_to :user, :counter_cache => true
belongs_to :book, :counter_cache => true
Migration file :
class AddBookStoriesCountColumn < ActiveRecord::Migration
def self.up
add_column :books, :book_stories_count, :integer, :null => false, :default => 0
Book.reset_column_information
Book.find_each do |b|
Book.reset_counters b.id, :stories
end
end
def self.down
remove_column :books, :book_stories_count
end
end
Index view :
ActiveAdmin.register Book do
index do
column :id
column :title
column :subtitle
column :isbn_13
column :book_stories_count
default_actions
end
I also created a rake task to manually update the counter if needed :
task :update_counters => [:environment] do
Book.reset_column_information
Book.find_each do |b|
Book.reset_counters b.id, :stories
end
Now, I would like to implement a stories counter for the users. And I believed I'll just have to use the same code up here, just changing "Book" with "User", but I have another problem.
User model :
class User < ActiveRecord::Base
has_many :book_actions
has_many :book_stories
has_many :books, through: :book_stories
but I encouter an error when I try to update / reset the counter
NoMethodError: undefined method `options' for nil:NilClass
Still investigating...
Every post has only one category, and i need to access category's name by something like
p = Post.new
p.category.name = "tech"
p.save
How to do that?
class Category < ActiveRecord::Base
has_many :posts, :dependent => :destroy
attr_accessible :name, :image
end
Post.rb
class Post < ActiveRecord::Base
belongs_to :category
attr_accessible :category_id, :name, :text, :lang, :image
end
Schema.rb
create_table "categories", :force => true do |t|
t.string "name"
t.string "image"
end
Your example contains a problem.
p = Post.new
p.category.name = "tech"
p.save
First, you create a new post. Second, you want to assign a name to the category of the post, BUT there is no category assigned. This results in a call like post.nil.name where nil would be the category object, if assigned, which isn't the case. Since nil has no method name, you get the described error undefined method name for nil class.
To solve this, you first need to assign a category to work on.
p.category = Category.first or p.category_id = 1. After that, p.category will return the category object, therefore p.category.name is valid then because it is called on a category object and not on nil.
tl;dr:
p = Post.new
p.category # => nil
p.category.name # throws an error
p.category = Category.first
p.category # => <#Category ...>
p.category.name # => 'actual name of category'
p.category.name = 'foo' # works now
The problem is that you need/want to explicitly build the category record if it doesn't exist.
To solve the problem, I'd think about creating a category_name= method in Post:
A category_name= settor would also take care of the "law of Demeter" issue
class Post < ActiveRecord::Base
belongs_to :category
attr_accessible :category_id, :name, :text, :lang, :image
attr_accessible :category_name=, :category_name
def category_name=(name)
self.category = Category.find_or_create_by_name(name)
end
def category_name
category && category.name
end
end
See also "Association Extensions" in the ActiveRecord docs for another way to do this.