Rails Papertrail - display who Was Responsible for last change - ruby-on-rails

I'm using Devise and Papertrail and would like to display which user made the most recent update (documentation link).
In controller:
def show
# #history = #person.versions.last
#last_change = #person.versions.last
#user_who_made_the_change = User.find #last_change.whodunnit.to_i
end
In show page
<%= #user_who_made_the_change %>
However I get the resulting error:
undefined method `whodunnit' for nil:NilClass
in app/controllers/people_controller.rb:15:in `show'
Any help would be much appreciated, thanks

I prefer to modify initializer to kept template clean.
config/initializers/paper_trail.rb
PaperTrail::Rails::Engine.eager_load!
module PaperTrail
class Version < ::ActiveRecord::Base
belongs_to :user, foreign_key: :whodunnit
end
end
history.html.erb
<% #versions.each do |version| %>
<%= version.user.email %>
<% end %>

There are many reasons for omit save version data (configuration, save without callbacks, save from console ...)
I think you must check if you have the information to show:
def show
#last_change = #person.versions.last
#user_who_made_the_change = (User.find(#last_change.whodunnit.to_i) if #last_change && #last_change.whodunnit) || nil
end
This must do the trick.

I've done a bit of googling this evening about this topic. I simply wanted to be able to write something like #post.versions.last.user and get the devise User record (ie the person whodunnit that version).
The way that worked for me was creating the paper_trail.rb initializer with
PaperTrail::Rails::Engine.eager_load!
module PaperTrail
class Version < ActiveRecord::Base
include PaperTrail::VersionConcern
belongs_to :user, foreign_key: :whodunnit
end
end
Some solutions gave me errors including json col not set or something and/or undefined methodtimestamp_sort_order'`.
This is just what worked for me.
Other options included creating this in your app/models which I liked the idea of but never tried cause this 'worked' and I have other code I want to write :)

Related

Model's changes for Algolia not showing in the rails console in PRODUCTION

I have a model as bellow:
class Note < Record
include Shared::ContentBasedModel
algoliasearch disable_indexing: AppConfig.apis.algolia.disable_indexing do
attributes :id, :key
[:keywords, :tags, :description, :summary].each do |attr|
attribute [attr] do
self.meta[attr.to_s]
end
end
attribute :content do
Nokogiri.HTML(self.meta["html"]).text.split(' ').reject { |i| i.to_s.length < 5 }.map(&:strip).join ' '
end
attribute :photo do
unless self.meta["images"].blank?
self.meta["images"].first["thumb"]
end
end
attribute :slug do
to_param
end
attribute :url do
Rails.application.routes.url_helpers.note_path(self)
end
end
end
I am using AlgoliaSearch gem to index my models into the Algolia's API and when I was trying to index the model with some long content I get the following error:
Error: Algolia::AlgoliaProtocolError (400: Cannot POST to https://XXXX.algolia.net/1/indexes/Note/batch: {"message":"Record at the position 1 objectID=56 is too big size=20715 bytes. Contact us if you need an extended quota","position":1,"objectID":"56","status":400} (400))
After this, I removed EVERYTHING as the following, BUT I am still getting the exact same error!!
class Note < Record
include Shared::ContentBasedModel
algoliasearch disable_indexing: AppConfig.apis.algolia.disable_indexing do
attributes :id
end
end
It seems that Rails does not update the cached models.
Envirnoment: production
Rails version: v6
Question: Why is this happening & how can I clear cached model?
Note: I have tried everything, including removing the tmp/cache folder but it does not go away!
It looks like the object's size itself is bigger than some max allowed size.
objectID=56 is too big size=20715 bytes
Contact https://www.algolia.com/ (as the suggest)
Contact us if you need an extended quota
How do you check your code? Are you entering in rails console on your server? Might it be that you run an old release instead of the new one, in the case if you use Capistrano or Mina for deploy?

undefined method `price_tier' for nil:NilClass

Wondering if someone can help me find this issue. I'm using rails 4, ruby 2, and have spent alot of time trying different accessors, etc and nothing has worked.
The whole plan model:
class Plan < ActiveRecord::Base
has_many :users
end
Some of the user model:
class User < ActiveRecord::Base
...
validate :plan_type_valid
belongs_to :plan
...
def plan_type_valid
if free_ok
# the following line causes error
valid_plans = Plan.where(price_tier: plan.price_tier).pluck(:id)
else
valid_plans = Plan.where(price_tier: plan.price_tier).where.not(stripe_id: 'free').pluck(:id)
end
unless valid_plans.include?(plan.id)
errors.add(:plan_id, 'is invalid')
end
end
end
Here's a pastebin of the whole users controller:
http://pastebin.com/GnXz3R8k
the migration was all messed up because of a superuser issue and it wasn't able to create the extensions for hstore field type.

RoR - Global method for all models

I got a little problem to understand where should I add an method that all the models can have access to it. I read other similar posts but it's not very clear where to add it. Some of them said about add it on "/lib" as a module an then include it in the model class (Already try this without luck). So what it's the best practice for add this?
I'm trying the following:
My module on: /lib/search.rb
module Search
def self.search(params,columns_search)
srch = params[:search]
if srch.blank?
scoped
else
search= []
#Add conditions for the search
columns_search.map do |column|
search << (sanitize_sql_for_conditions ["LOWER(CAST(#{column} as TEXT)) LIKE ?", "%#{srch.downcase}%"])
end
where("(#{conditions.join(" and ")})")
end
end
On my model cars.rb
class Cars < ActiveRecord::Base
include Search
attr_accessible :name
end
But i'm getting the following error on my console:
Started GET "/cars" for 127.0.0.1 at 2012-08-01 11:56:54 -0500
ActionController::RoutingError (uninitialized constant Car::Search):
app/models/car.rb:2:in `'
Any help will be appreciated! :)
The technique you mention seems like a reasonable approach - create a module (which will probably live in /lib) that defines the methods you want the models to have, and then include it in each model that needs it.
For instance, my current project has Images, Videos and Audios, all of which have certain method that should be available to them because they're all types of media.
I define a module in lib/media.rb:
module Media
def self.included(base)
# Associations etc. go here
base.has_many :things
base.mount_uploader :image, ImageUploader
base.attr_accessible :image
base.before_save :do_something
end
def do_something(argument=nil)
#stuff
end
end
And then in each of the media models, I include it:
class Video < ActiveRecord::Base
include Media
end
I can then call Video.first.do_something, just as though the method were defined in the model.

No foreign key in new scaffold

Good day... I have huge trouble with this and it drives me insane.
My user creation should have some additional data, like this:
<div class="field"><%= label_tag 'species', %>
<%= f.collection_select :species_id, Species.all, :id, :name %></div>
It displays the list of species correctly, yes, but when I do a submit, it is utterly ignored. Not even the number appears in the table of the database, it just disappears. I have put the correct associations:
class Species < ActiveRecord::Base
has_many :users
end
class User < ActiveRecord::Base
# ... Other stuff
belongs_to :species
# ... Other stuff
end
I have also tried manipulating the controller:
class UsersController < ApplicationController
def create
logout_keeping_session!
#user = User.new(params[:user])
#user.species = Species.find(params[:species_id])
# Other stuff
end
end
But that only gives me 'Cannot find Species without id' even though the params array contains an element 'species_id' with a value.
I am at the end of my wits. Quite new to this, but is this RESTful? Not to find out how to get things done that seem easy? I love Rails and would like to continue.
Thanks for listening
your find fails because the params is probably: params[:user][:species_id] but if it is there like it is supposed, it should be set already, too.

How do I handle nils in views?

I have the following models set up:
class Contact < ActiveRecord::Base
belongs_to :band
belongs_to :mode
validates_presence_of :call, :mode
validates_associated :mode, :band
validates_presence_of :band, :if => :no_freq?
validates_presence_of :freq, :if => :no_band?
protected
def no_freq?
freq.nil?
end
def no_band?
band.nil?
end
end
class Band < ActiveRecord::Base
has_many :logs
end
class Mode < ActiveRecord::Base
has_many :logs
end
When I enter a frequency on my new view it allows for no band to be specified if a freq is entered. This creates a problem in my other views though because band is now nil. How do I allow for band not to be specified and just show up as empty on my index and show views, and then in the edit view allow one to be specified at a later point in time.
I have been able to get my index to display a blank by doing:
contact.band && contact.band.name
But I'm not sure if this is a best approach, and I'm unsure of how to apply a similar solution to my other views.
Many thanks from a rails newb!
In my views, I use the following for potentially nil objects in my views:
<%= #contact.band.name unless #contact.band.blank? %>
if your object is an array or hash, you can use the empty? function instead.
<%= unless #contacts.empty? %>
..some code
<% end %>
Hope this helps!
D
A couple years old but still a top Google result for "rails view handle nil" so I'll add my suggestion for use with Rails 3.2.3 and Ruby 1.9.3p0.
In application_helper.rb, add this:
def blank_to_nbsp(value)
value.blank? ? " ".html_safe : value
end
Then to display a value in a view, write something like this:
<%= blank_to_nbsp contact.band %>
Benefits:
"blank" catches both nil values and empty strings (details).
Simply omitting a nil object, or using an empty string, may cause formatting issues. pushes a non-breaking space into the web page and preserves formatting.
With the "if" and "unless" suggestions in other answers, you have to type each object name twice. By using a helper, you only have to type each object name once.
<%= #contact.try(:band).try(:name) %>
This will return nil if band or name do not exist as methods on their respective objects.
You can use Object#andand for this:
<%= #contact.band.andand.name %>
<%= #contact.band if #contact.band %> also works

Resources