Rails: Updating two fields of an ActiveRecord instance simultaniously - ruby-on-rails

I have a model, called Book, that has the fields title and filename (and other fields but they are unrelated). I'd like that the filename field was automatically created using the title, thus in my Book.rb:
class Book < ActiveRecord::Base
# ...
def title=(title)
self.filename = sanitize_filename(title)
self.title = title
end
# ...
end
Because of self.title = title it's going in a infinite recursion. How could I avoid that?
Thanks!

You can write that on before_save
def before_save
self.filename = sanitize_filename(self.title)
end

Try this way
class Book
def title=(title)
self.filename = sanitize_filename(title)
self[:title] = title
end
end

There's a section in the ActiveRecord api on 'overwriting default accessors'. The suggested solution there is:
def title=(t)
self.filename = sanitize_filename(t)
write_attribute(:title, t)
end

Related

How can i change a field in a model as per another field?

Greetings fellow developers.
I have a model candidate.rb and there are 2 columns(offer_code and candidate_type) that i want to work with.
I want the offer_code = "CHP" if the candidate_type = "chapter".
I am trying to do this with after_save but this is creating all the new candidates with candidate_type = "chapter".
I think the condition that I have used is wrong. Please guide me
In candidate.rb
After_save : chapter_offer
def chapter_offer
If self.candidate_type = "chapter"
self.offer_code = "CHP"
end
end
You are using = for comparison instead of ==
And it will be better if you did something like this
before_save :chapter_offer, if: -> { candidate_type == 'chapter' }
def chapter_offer
offer_code = 'CHP'
end

How to convert string to existing attribute in model when creation

I got a array of strings, I want to retrieve for each the attribute during the creation of the post.
My array = ["_646_maturity", "_660_maturity", "_651_maturity", "_652_maturity", "_641_maturity"]
class Audit < ApplicationRecord
belongs_to :user
before_save :calculate_scoring
def calculate_scoring
scoring = []
models = ActiveRecord::Base.connection.tables.collect{|t| t.underscore.singularize.camelize.constantize rescue nil}
columns = models.collect{|m| m.column_names rescue nil}
columns[2].each do |c|
if c.include? "maturity"
Rails.logger.debug 'COLUMN : '+c.inspect
scoring.push(c)
end
end
getMaturity = ""
scoring.each do |e|
getMaturity = e.to_sym.inspect
Rails.logger.debug 'MATURITY : '+getMaturity
end
end
end
The log print > 'MATURITY : :_651_maturity'
I'm looking to the value of :_651_maturity who is a attribute of my post.
I tried .to_sym but it's not working..
Thanks for the help!
Inside calculate_scoring you can use self to point to the record you are saving. So self._651_maturity = <some_value>, self[:_651_maturity] = <some_value> and self['_651_maturity'] are all valid methods to set _651_maturity.
Also, you can do something like:
my_attrib = '_651_maturity'
self[my_attrib] = 'foo'

I am getting error undefined method `to_sym' for nil:NilClass in Rails for updating image?

My controller
def update
handled_error_fields %i(location address1 address2 name name_kanji gender prefecture_code tel zip_code).collect { |s| :"primary_address.#{s}" }
if params[:salon].present?
if params[:salon].present?
if params[:salon][:tel].present?
tel = params[:staff][:tel]
params[:staff][:tel] = NKF.nkf('-W -w -m0 -Z0', tel)
end
end
if params[:staff][:email].present?
email = params[:staff][:email]
email.gsub!(/。/, '.')
params[:staff][:email] = NKF.nkf('-W -w -m0 -Z0', email)
end
end
if params[:staff]["staff_image"].present?
#staff_image = StaffImage.find_by_staff_id(current_staff.id)
if #staff_image.blank?
#staff_image = StaffImage.new
#staff_image.staff_id = current_staff.id
#staff_image.legacy_user_id = current_staff.legacy_user_id
#staff_image.image = params[:staff]["staff_image"]["image"].read
#staff_image.save!
else
#staff_image.image = params[:staff]["staff_image"]["image"].read
#staff_image.update_attribute('image', #staff_image.image)
end
end
super
end
My Model is
class StaffImage < ActiveRecord::Base
end
it has columns
staff_id,
image,
legacy_client_id.
Real problem is after insertion of image in database, I can't update the image. I am new to Rails. I know problem is in this line:
#staff_image.update_attribute('image', #staff_image.image)
Not using any attachment plugins? Have a look on https://github.com/thoughtbot/paperclip gem. Way too easy for handle this kind of things in Rails.
Not necessary to use update_attribute method. Simple save could solve.
#staff_image.image = params[:staff]["staff_image"]["image"].read
#staff_image.save
You might want to try calling "with_indifferent_access" like:
params = params.with_indifferent_access
before accessing "staff_image"
params[:staff]["staff_image"]["image"]
this should get rid of the error and then:
#staff_image.image = params[:staff]["staff_image"]["image"].read
#staff_image.save

ruby on rails accessing custom class attributes from its object

I have a custom class in my application controller. Like below:
class Defaults
def initialize
#value_1 = "1234"
#value_2 = nil
#data = Data.new
end
end
class Data
def initialize
#data_1 = nil
end
end
Now in my controller method i have created an object of type Defaults
def updateDefaultValues
defaults = Defaults.new
# i am unable to update the value, it says undefined method
defaults.value_2 = Table.maximum("price")
defaults.data.data_1 = defaults.value_2 * 0.3
end
How to access value_2 from defaults object?
defaults.value_2
Also, how to access data_1 attribute from data object within defaults object?
defaults.data.data_1
You should use attr_accessor:
class Defaults
attr_accessor :value_1, :value_2, :data
# ...
end
defaults = Defaults.new
defaults.value_1 = 1
# => 1
defaults.value_1
# => 1
As you are using def as a keyword to define the method, that means def is a reserved keyword. You can't use reserved keywords as a variable.
You just need to rename your variable name from def to something_else and it should work! Your code will look like this:
def updateDefaultValues
obj = Defaults.new
obj.value_2 = Table.maximum("price")
obj.data.data_1
end
EDIT:
As per OP's comment & updated question, he had used def just as an example, here is the updated answer:
You may need attr_accessor to make attrs accessible:
class Defaults
attr_accessor :value_1, :value_2, :data
...
...
end
class Data
attr_accessor :data_1
...
...
end
Add value_2 method in Defaults class
class Defaults
def initialize
#value_1 = "1234"
#value_2 = nil
#data = Data.new
end
def value_2
#value_2
end
end
class Data
def initialize
#data_1 = nil
end
end

better way to build association in controller

I need a link in a show method of a parent class for creating associated models, so I have the code:
link_to "incomplete", new_polymorphic_path(part_c.underscore, :survey_id => survey.id)
in a helper.
This links to a part, which has new code like this:
# GET /source_control_parts/new
def new
get_collections
if params[:survey_id]
#s = Survey.find(params[:survey_id])
if #s.blank?
#source_control_part = SourceControlPart.new
else
#source_control_part = #s.create_source_control_part
end
else
#source_control_part = SourceControlPart.new
end
end
I know this is not very DRY. How can I simplify this? Is there a RAILS way?
How about this:
def new
get_collections
get_source_control_part
end
private
def get_source_control_part
survey = params[:survey_id].blank? ? nil : Survey.find(params[:survey_id])
#source_control_part = survey ? survey.create_source_control_part : SourceControlPart.new
end

Resources