I have rails 2.3.11. i want to overwrite one of the database field value.But its not overwrite.
def after_find
add_public_uri
end
def add_public_uri
self.uri = uri.to_s
end
Not sure about the syntax, but have you tried
after_find: add_public_uri
private
def add_public_uri
self.uri = uri.to_s
end
Alternatively, you could simply have a customer reader in your model:
def uri
uri.to_s
end
Related
I have Memoized an object and thinking of adding cache to that variable.. is that a required if speed matters?
def user_details
#_user_details ||= user.profiles.includes(":asso_1,:asso_2,:asso_3")
end
adding cache
def user_details
data = Rails.cache.fetch("#{user.updated_at.to_i}") do
#_user_details ||= user.profiles.includes(":asso_1,:asso_2,:asso_3")
end
#_user_details = data
end
Change your caching key; make it something like: users_#{user.id};
Then you'll need to remove this key on user update.
Also, your user_details method should be something like:
def user_details
#_user_details ||= Rails.cache.fetch("users_#{user.id}") do
user.profiles.includes(":asso_1,:asso_2,:asso_3")
end
return #_user_details
end
(I'm not sure why you want it in #_user_details but I kept it like your example)
Your user model should look something like that:
class User < ApplicationRecord
...
after_update { Rails.cache.delete(cache_key) }
def cache_key
"users_#{self.id}"
end
def details
Rails.cache.fetch(cache_key) do
self.profiles.includes(":asso_1,:asso_2,:asso_3")
end
end
end
Let's say I have a method
after_create :create_slug
def create_slug
self.slug = "#{model}-#{make}-#{year}"
end
def update_slug(user)
user.slug = "#{model}-#{make}-#{year}"
user.save!
end
I am confused when do I need to explicitly save an object.
When you want to persist it as is and it's in a dirty state.
I recently had a rails model that had several callbacks on it like so:
class Model < ActiveRecord::Base
before_validation :fetch_posts
after_create :build_posts
def fetch_posts
fetch_collection
rescue MyException => e
self.errors.add(:post, e.message)
end
def build_posts
fetch_collection.each do |item|
DifferentModel.build(item)
end
end
def fetch_collection
#collection ||= method_that_fetches_collection_from_external_source
end
end
This was working just fine but it was making it extremely difficult to write tests, as whenever I wanted to create a Model I had to stub out all the callbacks. Enter service objects:
class ModelFetcher
attr_reader :model
def initialize(model)
#model = model
end
def save
model.fetch_posts
if model.save
model.build_posts
return true
else
return false
end
end
end
The problem I'm seeing now, in the case where a model does indeed contain an error (from the fetch posts method), it doesn't get carried over to the model.save call in the SO. That is to say, the Model.new has an error, but once I call .save on that Model.new it doesn't maintain the error and the model saves properly.
I considered adding validate :fetch_posts but then I am back in the same situation I was before as this is essentially a callback.
Any advice on how to structure this better? Is it possible to maintain an error from Model.new to .save? Am I fundamentally misunderstanding something?
Thanks!
Here is an alternate solution which is to overwrite run_validations! since you have none.
class Model < ActiveRecord::Base
after_create :build_posts
def fetch_posts
fetch_collection
rescue MyException => e
self.errors.add(:post, e.message)
end
def build_posts
fetch_collection.each do |item|
DifferentModel.build(item)
end
end
def fetch_collection
#collection ||= method_that_fetches_collection_from_external_source
end
private
def run_validations!
fetch_posts
errors.empty?
end
end
Usually this method looks like
def run_validations!
run_callbacks :validate
errors.empty?
end
but since you have no validations it should serve a similar purpose on #save.
Or as I suggested in a comment you can replace save with model.errors.any? Since save will clear your original errors set by fetch_posts but errors.any? Will check if there were errors during the fecth_posts method.
Looking for a way to either:
Change one of the fields of a new record (namely - force it to lower-case) before saving it to a RoR db.
I've tried:
before_create do |term|
term.myfield.downcase!
end
but this gives an error of:
undefined method `before_create' for RowsController:Class
or
Check that the field is all lowercase, and if not, raise an error message, and not create the record.
tried:
before_filter :check_lowcase, :only => [:new]
def check_lowcase
if (Term.new =~ /[^a-z]+/)
flash[:notice] = "Sorry, must use lowercase"
redirect_to terms_path
end
end
this seems to just be ignored....
You need to do it on your model, not your controller:
class YourModel < ActiveRecord::Base
before_create :downcase_stuff
private
def downcase_stuff
self.myfield.downcase!
end
end
before_create :lower_case_fields
def lower_case_fields
self.myfield.downcase!
end
before_save { |classname| classname.myfield = myfield.downcase }
I want to convert the title of a page to a friendly URL and store it in the database as a permalink. My problem is I can't use the parameterize method. It's not working. Other inflections are working like upcase or downcase but parameterize is not working. Is there a special case for parameterize?
This is my code:
Controller:
def create
params[:page][:permalink] = params[:page][:title].dup
#page = Page.new(params[:page])
end
Model:
class Page < ActiveRecord::Base
before_save :makeitpermalink
before_update :makeitpermalink
private
def makeitpermalink
permalink.parameterize!
end
end
According to the Rails' documentation, there is no bang (exclamation mark) version of the parameterize method, so try removing it:
def make_it_permalink
self.permalink = self.permalink.parameterize
end