Add model administration to Active Admin - Rails 3 - ruby-on-rails

I'm fairly new to Rails and ActiveAdmin.
I'd like to have an interface much like Django's admin, with my app models, so I can administer products, and other stuff.
So far I have the admin_users url where I can add or delete admin users to my app, that's wonderful.
I'm using Rails 3, and I was wondering if I can add a new menu besides Users so I can manage other models from the dashboard
I've tried rails generate active_admin:resource Product
It creates a file called product.rb on app/admin/ but it doesn't works, this is my Product model product.rb
class Product < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me
belongs_to :category
has_many :line_items
has_many :orders, through: :line_items
validates_presence_of :category_id, :name, :price_cents
attr_accessible :avatar
has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100>" }, :default_url => "/images/:style/missing.png"
validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
attr_accessor :price
attr_accessible :category_id, :description, :image, :name, :price_cents, :upc_code, :price, :taxable
def price
price_cents/100.0 if price_cents
end
def price= price
self.price_cents = (price.to_f*100).round
end
end
I don't know, what am I doing wrong?
Any ideas?

To register your Product model, run:
rails generate active_admin:resource Product
This creates a file at app/admin/product.rb for configuring the resource. Refresh your web browser to see the interface.
Please take a look at Active Admin Documentation for more details.

Under app/admin your product.rb file register the model. I would look something like
ActiveAdmin.register Product do
:category_id, :description, :image, :name, :price_cents, :upc_code, :price, :taxable
index do
selectable_column
id_column
column :description
column :name
column :price_cents
actions
end
form do |f|
f.inputs "Product Details" do
f.input :price
f.input :name
f.input :description
# more fields
end
f.actions
end
end
Look at the documentation for more info.

Related

Association undefined method `id'

Hello guys this error is giving me a headache for days and I seriously don't know what's happening. So, I have 2 models: User and Composition. Compositions have a belongs_to :user and the user have has_many :compositions and one controller which is giving an error when I try to get de user id from the composition's owner(user).
Error
undefined method `id' for nil:NilClass
<%= link_to profile_path(compos.user.id), class: 'ui-btn btn-small' do %>
<span class="icon-export"></span>visitar perfil</a>
<% end %>
Composition
class Composition < ApplicationRecord
belongs_to :user
validates :title, presence: true, :length => {maximum: 120}
validates :description, presence: true
has_attached_file :thumbnail
validates_attachment_content_type :thumbnail, content_type: /\Aimage/
validates_attachment_file_name :thumbnail, matches: [/png\Z/, /jpe?g\Z/]
do_not_validate_attachment_file_type :thumbnail
end
User
class User < ApplicationRecord
has_many :compositions
rolify
devise :database_authenticatable, :omniauthable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
mount_uploader :avatar, AvatarUploader
# Validações
validates_integrity_of :avatar
validates_processing_of :avatar
validates_format_of :username, :with => /[\w]+/
validates_length_of :username, :in => (5..32)
validates_uniqueness_of :username
#Previne que o avatar tenha um tamanho maior de 2MB
private
def avatar_size_validation
errors[:avatar] << "should be less than 2MB" if avatar.size > 2.megabytes
end
end
Controller
class StaticPagesController < ApplicationController
before_filter :authenticate_user!
def index
#compositions = Composition.all.order('created_at desc').limit(4)
end
end
You can set if condition to check if compos.user is present.
<% if compos.user %>
But, Seems like it's data inconsistency as I think you are working on development environment
You need to make sure for each composition user_id must exist.
class Composition < ApplicationRecord
belongs_to :user
validates :user, presence: true
end
This way you will never have compos with user_id = nil

Rails has_many belongs_to nil issue

I'm a Rails beginner and I'm currently adding some basic associations to my models. I have the following in my two models:
User model:
class User < ActiveRecord::Base
has_many :photos, dependent: :destroy
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
validates_uniqueness_of :username
end
Photos model:
class Photo < ActiveRecord::Base
belongs_to :user
has_attached_file :image,
styles: { medium: '300x300>', thumb: '100x100>' },
default_url: '/images/:style/missing.png'
validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/
end
After adding the above, I ran the appropriate migrations:
rails g migration AddUserIdToPhotos user_id:integer
rake db:migrate
The user_id was added to the Photos table but when I add a new photo, the user_id field is set to nil.
When I went to psql to double check there, it does not even show nil, just an empty field.
This is the code in the Photos Controller:
def create
photo = Photo.new(photo_params)
if photo.save
Pusher['the_force'].trigger('new_photo', {
url: photo.image.url(:medium),
description: photo.description,
id: photo.id
})
end
redirect_to '/'
end
private
def photo_params
params.require(:photo).permit(:image, :description, :user_id)
end
end
Any help here would be much appreciated.
If you are not passing the user from your form and you wants to save the user that is already logged in, you have to pass it when creating the photo instance.
photo = Photo.new(photo_params, :user => current_user)

Rails select from multiple tables to create collection for select field?

I'm trying to dynamically build a collection where each array contains a value from two separate tables.
The Models:
#/models/user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :confirmable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :user_id, :email, :password, :password_confirmation, :remember_me,
:first_name, :last_name, :permanent_address, :permanent_city,
:permanent_state, :permanent_zip, :home_phone, :mobile_phone, :role,
:tenant_attributes, :rents_attributes
validates :email, :presence => true, :uniqueness => true
validates :first_name, :presence => true
validates :last_name, :presence => true
validates :permanent_address, :presence => true
validates :permanent_city, :presence => true
validates :permanent_zip, :presence => true
validates :first_name, :presence => true
validates :home_phone, :presence => true
has_one :app
has_one :tenant, :foreign_key => :users_id
has_many :rents
has_many :maints
accepts_nested_attributes_for :tenant
accepts_nested_attributes_for :rents, allow_destroy: true
end
#/models/tenant.rb
class Tenant < ActiveRecord::Base
belongs_to :users
belongs_to :units
attr_accessible :lease_begin, :lease_end, :rent_share, :users_id, :units_id
has_many :maints
end
The Helper Method (so far):
#/helpers/users_helper.rb
def tenants
tenants = Tenant.select([:id, ??? ])
tenants.map {|u| [u.???, u.id]}
end
The form field:
<%= f.input :tenant_id, :collection => tenants %>
Essentially what I'm trying to do is select the :id from the Tenants table and then the associated :first_name + :last_name (represented by "???" above) from the Users table to populate the collection arrays this would generate.
What's the best approach here?
If your helper is specifically used just for this input then I believe you have the correct thought on your query, in that you are concerned on retrieving just the required columns.
To retrieve tenants including attributes from their belongs_to :user relation, your helper definition needs to be updated to:
# app/helpers/users_helper.rb
def tenants
tenants = Tenant.joins(:user).select('tenants.id as tenant_id, users.first_name, users.last_name')
tenants.map { |u| [ [u.first_name, u.last_name].join(' '), u.tenant_id ]}
end
The tenants helper then returns a nested array of first_name and last_name joined with a space as one element and tenant_id as the second element array.
With the updated helper your view would be:
<%= f.select :tenant_id, :collection => tenants %>
Note the use of select helper here which is more suitable for this case.

ActiveRecord - Find next user in group model

I've four user models: Zone, Product, User, Group
I want to choose what Users can sell a Product in a Zone, this is what Group does, with a many to many relation to User and a foreign key to one Product and one Zone. So I have one group per pair Zone/Product. I will also need to set custom attributes on that many to many relation so I used has_many :through Sell (I was unable to find a better name to describe the relation between Group and User).
So I ended up having 5 models: Zone, Product, User, Group, Sell.
It works fine, but now I'd need to select the next user available in a Group.
I was thinking to exploit Sell.id to find the user assigned to the same group with an higher id, if not present choose the first one again (this allows me to create a ring chain).
It would be useful to have a Group.next_user method.
Unfortunatly I can't figure out how to do this, I'd need help to find the next user available in the group (or the 1st one if there are no more users).
Follows the code for models all the models:
################
# models/group.rb
################
class Group < ActiveRecord::Base
has_many :sells
has_many :users, :through => :sells
belongs_to :zone
belongs_to :product
attr_accessible :priority, :product_id, :user_ids, :zone_id
end
################
# models/zone.rb
################
class Zone < ActiveRecord::Base
belongs_to :location
has_many :cities
has_many :groups
attr_accessible :name, :location_id
validates :location, :presence => true
end
################
# models/user.rb
################
class User < ActiveRecord::Base
after_create :create_calendar
before_destroy :destroy_calendar
belongs_to :location
belongs_to :mall
has_one :event_calendar
has_many :sells
has_many :groups, :through => :sells
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable, :registerable,
# :recoverable, :rememberable,
devise :database_authenticatable, :trackable,
:validatable, :authentication_keys => [:username]
# Setup accessible (or protected) attributes for your model
attr_accessible :username, :password, :password_confirmation, :remember_me, :name,
:surname, :role, :location_id
# attr_accessible :title, :body
ROLES = %w[Admin Agente Hostess HostessAdmin]
validates_uniqueness_of :username, :case_sensitive => false
validates :username, :presence => true
validates_presence_of :role, :name, :surname, :location_id
validates :location, :presence => true
validates :role, :inclusion => { :in => ROLES, :message => "%{value} non è un ruolo valido." }
def display_name
"#{self.name} #{self.surname}"
end
def has_role?(role)
# convert the role string to a sybmol
self.role.downcase.gsub(/\s+/, "_").to_sym == role
end
private
def create_calendar
if self.has_role? :agente
calendar = EventCalendar.new({:user_id => self.id})
calendar.save()
end
end
def destroy_calendar
if self.has_role? :agente
calendar = EventCalendar.find_by_user_id(self.id)
calendar.destroy()
end
end
def email_required?
false
end
def email_changed?
false
end
end
################
# models/product.rb
################
class Product < ActiveRecord::Base
after_create :create_groups
before_destroy :destroy_groups
attr_accessible :name
def create_groups
for zone in Zone.all
group = Group.new({:zone_id => zone.id, :product_id => self.id})
group.save()
end
end
def destroy_groups
for zone in Zone.all
group = Group.find_by_product_id(self.id)
group.destroy
end
end
end
################
# models/sell.rb
################
class Sell < ActiveRecord::Base
belongs_to :user
belongs_to :group
end
Can you give me some help to get this done? Thanks!
If I get this right then addd this to your User model
scope :next, lambda { |p| {:conditions => ["id > ?", p.id], :limit => 1, :order => "id"} }
and this to your group model
def self.next_user
return User.first if Group.users.blank?
next_user = User.next(Group.users.last).first
return next_user || Group.users.first
end
This should do the trick. I didn't write test for this so you should test it :)

Problems Displaying Values from Nested Form

I'm having issues displaying values from a nested controller. I can update the field just fine, I just cannot see the values on the show page. I think it's an issue with Devise.
My user model is as follows:
class User < ActiveRecord::Base
has_one :page
accepts_nested_attributes_for :page, :allow_destroy => true
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :name
has_friendly_id :name, :use_slug => true, :strip_non_ascii => true
validates_presence_of :name
validates_uniqueness_of :name
validates_uniqueness_of :email, :case_sensitive => false
#creates a new page on user create if one doesn't exist
def after_initialize
self.build_page if self.page.nil?
end
end
My pages model:
class Page < ActiveRecord::Base
belongs_to :user
attr_accessible :tagline, :about, :email, :phone, :website, :blog, :user,
end
routes.rb
Ahoy::Application.routes.draw do
resources :users, :path => '/' do
resource :page
end
devise_for :users, :controllers => { :registrations => "registrations"}
get "home/index"
get "home/about"
root :to => "home#index"
end
In my users#show I have this:
<p>
<strong>Tagline</strong>
<%= #user.tagline %>
</p>
And I get a undefined method. Have also tried, #pages.tagline etc.
I didn't think I needed to amend my controller? Can you help?
The tagline method is defined in Page, so it should be #user.page.tagline

Resources