Looking for a way to set a variable when doing Model.new

I need a way to set a counter that will show how many of the model
have been created and put this in each instance. This will allow me to
use the record number as an input to another field before id is set.
After things are settled, the real id number can be substituted for
the counter.

I’ve tried new in the controller, but that’s for a create action from
the app.

                                                       Thanks
                                                       Bob

On 8 February 2012 07:12, Bob S. [email protected] wrote:

I need a way to set a counter that will show how many of the model
have been created and put this in each instance. This will allow me to
use the record number as an input to another field before id is set.
After things are settled, the real id number can be substituted for
the counter.

If you do that and two users come along at the same time and make new
objects then they will both get the same number. Can you not just use
a before_save filter to set the field? If you think not can you
explain what you are trying to do (and why) in more detail as there is
almost certainly a better solution.

Colin

You can use also after_initialize checking if the counter is already
setted

after_initialize :set_counter

def set_counter
self.counter ||= ModelName.all.count
end

On 8 February 2012 11:05, grentis [email protected] wrote:

ModelName.all.count

Please don’t ever do this.
If you want a count of all the objects in a table, use
“ModeName.count”. Using “.all.count” will instantiate an array of all
of the objects just to do a count of the array… this could be very
slow with a big table.

Ops, sorry…I don’t know why I add .all :frowning:

On 08.02.2012, at 13:39, Colin L. wrote:

explain what you are trying to do (and why) in more detail as there is
almost certainly a better solution.

I think actually he asked about something counter-caching solution for
stand-alone model/table. Good question, for the best approach it has to
be realized on a database level. The second approach is to build
additional caching table to keep counter values for anything you want.
The last one is not so elegant.

On 08.02.2012, at 15:05, grentis wrote:

You can use also after_initialize checking if the counter is already setted

after_initialize :set_counter

def set_counter
self.counter ||= ModelName.all.count
end

Imagine ‘create’ action.

During the period from the instance is initialized:
@user = User.new(params[:user])
to the moment it saved
@user.save

anyone else can create user object(s), so your @user will be saved with
incorrect counter value.

On Wed, Feb 8, 2012 at 10:39 AM, Colin L. [email protected]
wrote:

explain what you are trying to do (and why) in more detail as there is
almost certainly a better solution.

Maybe the OP really wants a “sequence” (a guaranteed unique number
that is more or less monotomically going up).

The OP may be used to the concept that the primary ID of a record upon
creation is such a sequence. But maybe he needs that number before
the record is saved. (e.g. to set a serial number that is saved in the
record).

If that is the business requirement, 3 solutions:

  1. don’t do it that way. Use a separate sequence generator (which exists
    in Postgresql and probably in all databases) and use that to calculate
    the unique and more or less monoticly increasing serial number. Do NOT
    couple that “business id” with the actual internal database id.

  2. If you want to use the database id, then you could use an external
    sequence generator and set the Object.id manually before saving (than
    configure your db in a way that the primary key is set from the
    application).

  3. do an after_create (create the object with most data filled in, the
    create will generate the database id and in the after_create calculate
    the other field (e.g. serial number) and save again … this is then an
    “update” so the “after_create” will not be triggered again). You may
    need some more tricks to make sure this “serial number” field cannot
    be modified, otherwise it could be out of sync with you internal
    database
    id (that is “back to (1) above” don’t link the “serial number” with the
    database id, just make it a separate column with a unique index and
    use a separate sequencer to generate those unique codes).

HTH,

Peter

On Feb 8, 11:54pm, Bob S. [email protected] wrote:

the counter.
The OP may be used to the concept that the primary ID of a record upon

be modified, otherwise it could be out of sync with you internal database
after_create, after_initialize, and the database won’t help me… I
=> Person.new
record, and replace the counter with the correct value. Now all I need
is a way to set the counter at each new record. Hope this makes it
clearer.

Thanks
Bob

Just ALMOST fixed this thanks to google…

in person.rb
def initialize(params = nil)
super()
self.hoh = $hoh
$hoh = $hoh - 1
end

This will set the model to the value in $hoh and decrement it once,
but after that the $hoh = $hoh - 1 won’t execute. If I make more than
1 record, all values are the same… Please help!!

Thanks
Bob

On Feb 8, 7:11am, Peter V. [email protected] wrote:

a before_save filter to set the field? If you think not can you

application).

HTH,

Peter

It seems a bit of explanation is in order…

after_create, after_initialize, and the database won’t help me… I
need this value to be available as soon as new creates a new object in
the view, before any saving. I have the logic set to do this with
existing records. What I am trying to do is have a unique value set in
each new record so that they can be part of a radio button list.

This is how the new objects are created

<%= link_to_function “Add a Person” do |page|
page.insert_html :bottom, ‘empty’, :partial => ‘shared/
person’, :locals => {:temp => @temp,:household => @household}, :object
=> Person.new
end %>

My app is used at the signup table of a foodbank. My app has a
household record that has address, zip, phone, etc. This has a child
model called people with… guess what… people :> There are radio
buttons referencing the record id next to each person where the head
of household can be selected. This is where the problem lies. No
problem with existing people, but new ones have no id yet. I have
added a variable to the people model to hold a counter. I have the
logic to look back at the record after save, find the id of the wanted
record, and replace the counter with the correct value. Now all I need
is a way to set the counter at each new record. Hope this makes it
clearer.

Thanks
Bob

On Wed, Feb 8, 2012 at 8:54 PM, Bob S. [email protected] wrote:

What I am trying to do is have a unique value set in each new record

See: http://rubygems.org/gems/uuid

HTH!

Hassan S. ------------------------ [email protected]
http://about.me/hassanschroeder
twitter: @hassan

On Thu, Feb 9, 2012 at 7:07 AM, Hassan S.
<[email protected]

wrote:

On Wed, Feb 8, 2012 at 8:54 PM, Bob S. [email protected] wrote:

What I am trying to do is have a unique value set in each new record

See: http://rubygems.org/gems/uuid

Indeed.

And maybe better to not mess with the def initialize, but use the
after_initialize function that is provided by Rails. I did it like
this.

…/lib/uuid_helper.rb

require ‘uuidtools’

module UUIDHelper
extend ActiveSupport::Concern

included do
after_initialize :set_uuid
def set_uuid
unless uuid # Note 1 below
self.uuid = UUIDTools::UUID.random_create.to_s
end
end
end
end

…/app/model/person.rb

class Person < ActiveRecord::Base

UUID

include UUIDHelper

end

Note 1:
Be careful, it is a little tricky to only set the value of the uuid
when it is not yet present, otherwise reading back the value
from the database will build a new instance of Person with a
new random uuid. The code above is well tested and works.

Maybe you will also need to add …/lib to your default load path.
In config/application.rb

# Custom directories with classes and modules you want to be

autoloadable.
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]

HTH,

Peter

*** Available for a new project ***

Peter V.
http://twitter.com/peter_v
http://rails.vandenabeele.com
http://coderwall.com/peter_v

On Feb 11, 2:33pm, Bob S. [email protected] wrote:

end

autoloadable.

I don’t have a config/application.rb. Forgot to mention it, but I’m
using 2.3.9 until I get rid of bugs, then the 3.0 project starts… :>
Can this be done for 2.3.9?

Thanks
Bob

Finally found it. Here it is for anyone else in similar trouble.

In the view

<%= link_to_remote “Add a Person”, :url => “/people/add_person” %>

In the controller

def add_person
person = Person.new()
person.hoh = $hoh
$hoh = $hoh - 1
render :update do |page|
page.insert_html :bottom, ‘empty’, :partial => ‘shared/
person’, :object => person
end
end

This will add a new object AND allow the play with the hoh in the new
model AND decrement it for the next new object.
As usual, everything is possible in Rails, once you find an allowed
way to do it,

Bob [email protected]

On 26 February 2012 21:32, Bob S. [email protected] wrote:

end
Global variables?
For the love of all that’s OO, at least hide it behind a singleton :-/
shakes head

On Feb 9, 3:52am, Peter V. [email protected] wrote:

included do

from the database will build a new instance of Person with a
HTH,

Peter

*** Available for a new project ***

Peter
Vandenabeelehttp://twitter.com/peter_vhttp://rails.vandenabeele.comhttp://coderwall.com/peter_v

I don’t have a config/application.rb. Forgot to mention it, but I’m
using 2.3.9 until I get rid of bugs, then the 3.0 project starts… :>
Can this be done for 2.3.9?

Thanks
Bob

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs