I have rails 3 application with some models, like Product and User. I'm using "audited" gem to track changes for products, it's simple and nice working.
But I want to make special page where I want to put daily activity history. I need something like Audits.all.order("created_at") for first step, but there is no such model.
Question: How can I get all audits for today for all models?
I think you should query like Audited::Adapters::ActiveRecord::Audit.where("created_at >= ?", Date.today) according to the gem structure
To be able to access today's audits with:
#audits = Audit.today
Create an audit.rb file in app/models/ like:
Audit = Audited.audit_class
class Audit
scope :today, -> do
where("created_at >= ?", Time.zone.today.midnight).reorder(:created_at)
end
end
Audited also provides a few named scopes of its own that may prove useful:
scope :descending, ->{ reorder("version DESC") }
scope :creates, ->{ where({:action => 'create'}) }
scope :updates, ->{ where({:action => 'update'}) }
scope :destroys, ->{ where({:action => 'destroy'}) }
scope :up_until, ->(date_or_time){ where("created_at <= ?", date_or_time) }
scope :from_version, ->(version){ where(['version >= ?', version]) }
scope :to_version, ->(version){ where(['version <= ?', version]) }
scope :auditable_finder, ->(auditable_id, auditable_type){ where(auditable_id: auditable_id, auditable_type: auditable_type) }
my solution is simply to extend the audit object, e.g.
cat lib/audit_extensions.rb
# The audit class is part of audited plugin
# we reopen here to add search functionality
require 'audited'
module AuditExtentions
def self.included(base)
base.send :include, InstanceMethods
base.class_eval do
belongs_to :search_users, :class_name => 'User', :foreign_key => :user_id
scoped_search :on => :username, :complete_value => true
scoped_search :on => :audited_changes, :rename => 'changes'
scoped_search :on => :created_at, :complete_value => true, :rename => :time, :default_order => :desc
scoped_search :on => :action, :complete_value => { :create => 'create', :update => 'update', :delete => 'destroy' }
before_save :ensure_username
end
end
module InstanceMethods
private
def ensure_username
self.username ||= User.current.to_s rescue ""
end
end
end
Audit = Audited.audit_class
Audit.send(:include, AuditExtentions)
Related
Its not accepting Texts except Numeric figures. I created a Private method in my page.rb of my Model which is not callable from outside Model: page.rb so as to automatically fix in Permalink for users incase it's not provided. Despite, still not texts except numbers.
Here is few details about my code from my Model:
page.rb
class Page < ActiveRecord::Base
belongs_to :subject
has_many :sections
has_and_belongs_to_many :editors, :class_name => 'AdminUser'
acts_as_list :scope => :subject
before_validation :add_default_permalink
after_save :touch_subject
validates_presence_of :name
validates_length_of :name, :maximum => 255
validates_presence_of :permalink
validates_length_of :permalink, :within => 3..255
# use presence_of with length_of to disallow spaces
validates_uniqueness_of :permalink
# for unique values by subject use ":scope => :subject_id"
scope :visible, lambda {where(:visible => true)}
scope :invisible, lambda {where(:visible => false)}
scope :sorted, lambda {order('pages.position ASC')}
scope :newest_first, lambda {order('pages.created_at DESC')}
scope :search, lambda {|query| where('name LIKE ?', "%#{query}%")}
private
def add_default_permalink
if permalink.blank?
self.permalink = "#{id}-#{name.parameterize}"
end
end
def touch_subject
# touch is similar to:
# subject.update_attributes(updated_at, Time.now)
subject.touch
end
end
See picture for the error here
Error
if I add number up to 3 to this or put in just numbers, the program works well bet takes no text alone.
As am working on the Active Admin(0.5) with Rails 3.2.3 Using Multilingual Support using Globalise 3 .
When am running application on local under development & production environment everything works great.
But when i deployed it on to the heroku production mode it throwing me error with the same code am using over local.
When i click on create new page it giving me below error:
NoMethodError in Admin::HomeTemplatesController#new
undefined method `build_app_page' for nil:NilClass
Rails.root: /app
Application Trace | Framework Trace | Full Trace
app/admin/home_templates.rb:16:in `new'
Please find below the code
ActiveAdmin.register HomeTemplate do
menu false
config.clear_action_items!
form :partial => "form"
controller do
protect_from_forgery :except => :sort
def new
# #home_template =HomeTemplate.new
# if !!current_ability.attributes_for(:create, HomeTemplate)[:app_instance_id]
# #valid_parents = AppPage.where("app_instance_id = ? AND parent_id IS NULL", current_ability.attributes_for(:create, HomeTemplate)[:app_instance_id])
# end
#home_template.build_app_page
end
def create
# if !!current_ability.attributes_for(:create, HomeTemplate)[:app_instance_id]
# #valid_parents = AppPage.where("app_instance_id = ? AND parent_id IS NULL", current_ability.attributes_for(:create, HomeTemplate)[:app_instance_id])
# end
if #home_template.present?
#home_template.app_page.protected = false;
#home_template.app_page.hidden = false;
#home_template.app_page.app_instance = #home_template.app_instance;
create!
end
end
def update
##home_template = HomeTemplate.find(params[:id])
#valid_parents = AppPage.where("app_instance_id = ? AND parent_id IS NULL", #home_template.app_page.app_instance_id)
update!
end
def edit
# if !!current_ability.attributes_for(:edit, HomeTemplate)[:app_instance_id]
# #valid_parents = AppPage.where("app_instance_id = ? AND parent_id IS NULL", current_ability.attributes_for(:edit, HomeTemplate)[:app_instance_id])
# Rails.logger.info( #valid_parents)
# Rails.logger.info( current_ability.attributes_for(:edit, HomeTemplate)[:app_instance_id])
# end
Rails.logger.info( "Home template outside")
##home_template = HomeTemplate.find(params[:id])
#valid_parents = AppPage.where("app_instance_id = ? AND parent_id IS NULL", #home_template.app_page.app_instance_id)
Rails.logger.info(#valid_parents)
end
end
collection_action :sort, :method => :post do
if(params[:ids])
params[:ids].each_with_index do |id, index|
app_page = AppPage.find(id)
app_page.move_to_child_of app_page.parent_id if can? :update, app_page.templatable
end
end
head 200
end
end
I tried to connect with console through heroku & it fetching the models.
I also checked the postgres database over local in production ode & all worked like a charm.
Right now am using Sqlite & postgres over local & heroku as postgres.
Your Help & guidance will be highly appreciable & deserves a hat off from my side.
Please let me know if any more details required.
Right now am using Polymorphic Association
as below
class HomeTemplate < ActiveRecord::Base
include BelongsToAppInstance
has_one :app_page, :as => :templatable
has_many :home_banner_images, :dependent => :destroy
accepts_nested_attributes_for :home_banner_images, :allow_destroy => true
accepts_nested_attributes_for :app_page
validates_presence_of :app_page
end
AppPages as:
class AppPage < ActiveRecord::Base
include BelongsToAppInstance
belongs_to :last_modified_by, :class_name => "AdminUser"
validates_presence_of :last_modified_by
belongs_to :templatable, :polymorphic => true, :dependent => :destroy
has_many :app_page_callouts
acts_as_nested_set
attr_readonly :hidden
attr_readonly :protected
default_scope :order => 'lft ASC'
validates_presence_of :name
#validates_uniqueness_of :name, :scope => :app_instance_id
validates_uniqueness_of :app_page_role, :scope => :app_instance_id
mount_uploader :related_pdf, PdfUploader
validate :parent_must_belong_to_same_app_instance
#validates_inclusion_of :linked_model, :in => AppPage.allowable_linked_models, :unless => Proc.new {|app_page| app_page.linked_model.blank? }
attr_accessible :name,:subtitle,:body,:app_page_attributes,
:app_instance_id,:app_page_role,:related_pdf,
:parent_id,:translations_attributes,
:last_modified_by,:app_instance,:sort,:view_controller,:hidden,:protected,:app_page_callouts,:parent
active_admin_translates :name,:subtitle,:body
#validates_globalized_uniqueness_of :name,:scope => :locale
def parent_must_belong_to_same_app_instance
if !self.parent_id.nil? && self.parent.app_instance_id != self.app_instance_id
errors.add(:parent_id, "The parent must belong to the same app instance.")
end
end
def set_view_controller
if self.view_controller.nil?
self.view_controller = "detail"
end
end
end
class Anketum < ActiveRecord::Base
has_one :user
class << self
def search(params)
self.scope :h, :conditions => {:height => params[:height]}
#scope :w, :conditions => {:width => params[:width]}
self.h if params[:height]
end
end
end
I need to create multiple scope depend on params[:xxx] present
Judging by your code sample, you're way over-engineering this:
# app/models/anketum.rb
class Anketum < ActiveRecord::Base
end
# app/controller/some_controller.rb
def search
#results = Anketum.scoped
[:width, :height, :any, :other, :searchable, :attribute].each do |key|
#results.where(key => params[key]) if params[key].present?
end
end
Your models should never access the params hash, by the way.
In my Rails project I'm using Formtastic to manage my forms. I have a model, Tags, with a column, "group". The group column is just a simple hardcoded way to organize my tags. I will post my Tag model class so you can see how it's organized
class Tag < ActiveRecord::Base
class Group
BRAND = 1
SEASON = 2
OCCASION = 3
CONDITION = 4
SUBCATEGORY = 5
end
has_many :taggings, :dependent => :destroy
has_many :plaggs, :through => :taggings
has_many :monitorings, :as => :monitorizable
validates_presence_of :name, :group
validates_uniqueness_of :name, :case_sensitive => false
def self.brands(options = {})
self.all({ :conditions => { :group => Group::BRAND } }.merge(options))
end
def self.seasons(options = {})
self.all({ :conditions => { :group => Group::SEASON } }.merge(options))
end
def self.occasions(options = {})
self.all({ :conditions => { :group => Group::OCCASION } }.merge(options))
end
def self.conditions(options = {})
self.all({ :conditions => { :group => Group::CONDITION } }.merge(options))
end
def self.subcategories(options = {})
self.all({ :conditions => { :group => Group::SUBCATEGORY } }.merge(options))
end
def self.non_brands(options = {})
self.all({ :conditions => [ "`group` != ? AND `group` != ?", Tag::Group::SUBCATEGORY, Tag::Group::BRAND] }.merge(options))
end
end
My goal is to use Formtastic to provide a grouped multiselect box, grouped by the column, "group" with the tags that are returned from the non_brands method. I have tried the following:
= f.input :tags, :required => false, :as => :select, :input_html => { :multiple => true }, :collection => tags, :selected => sel_tags, :group_by => :group, :prompt => false
But I receive the following error:
(undefined method `klass' for
nil:NilClass)
Any ideas where I'm going wrong?
Thanks for looking :]
I'm not sure we support :group_by with a custom :collection. In fact, that who part of the code was a messy contribution. So, try omitting the :collection for starters, and see where you end up. If there's a bug with Formtastic, please add an issue on Github.
I'd first move your Group class out of this file, and just inherit from where you want, or use a Module in this class. This is the preferred way of getting methods an constants into a class and staying organized.
In Rails, you can add a block after a named_scope for additional, context-sensitive methods like so:
class User < ActiveRecord::Base
named_scope :inactive, :conditions => {:active => false} do
def activate
each { |i| i.update_attribute(:active, true) }
end
end
end
In this example, the activate method is being defined not on the User class, but on the ActiveRecord::NamedScope::Scope object.
I have a series of three scopes that need to have identical method definitions. In the interests of not repeating code, how would I abstract that block such that I could define it once and pass it to each named_scope?
Firstly, great question--I didn't know about that feature of named scopes! The following works for me:
class User < ActiveRecord::Base
add_activate = lambda do
define_method "activate" do
each { |i| i.update_attribute(:active, true) }
end
end
named_scope :inactive, :conditions => {:active => false}, &add_activate
end
You can pass the add_activate block as the last argument to any named scopes that need the activate method.
Much better:
http://tuxicity.se/rails/dry/2009/01/04/share-named-scopes-in-rails.html
module NamedScope
def self.included(base)
base.class_eval do
named_scope :inactive, :conditions => {:active => false} do
def activate
each { |i| i.update_attribute(:active, true) }
end
end
end
end
end
Save in your /lib directory (put a require in an initializers in rails 3) and include NamedScope in your User class