views:

83

answers:

4

In rails default controller the new method makes an object, and the create method is used later to save that.

I want to set a mod_user field in the DB, without it being input into the form.

Based on this link http://api.rubyonrails.org/classes/ActiveRecord/Base.html I've tried adding the following to my pages controller.

  def new
    @page = Page.new(:n_publisher_id => session[:n_publisher_id])

or

  def create
    page = Page.new(params[:page])
    page.n_publisher_id = session[:n_publisher_id]

But it is saving as NULL If I put this in the controller and model then I get nil object errors from ActiveRecord

  def new
    @page = Page.new(1)

  def initialize(n_publisher)
    @n_publisher_id = n_publisher
  end

I have attr_accessor :n_publisher_id included in my page model. This works in the console...

>> @i = Page.new
=> #<Page id: nil, fk_issue: nil, n_status_id: nil, dt_published_datetime: nil, dt_offline_date: nil, dt_created_date: nil, n_publisher_id: nil, created_at: nil, updated_at: nil, page_name: nil>
>> @i.n_publisher_id
=> nil
>> @i.n_publisher_id = 1
=> 1
>> @i.n_publisher_id
=> 1

Here is schema of the pages table

mysql> show fields from pages;
+-----------------------+--------------+------+-----+---------+----------------+
| Field                 | Type         | Null | Key | Default | Extra          |
+-----------------------+--------------+------+-----+---------+----------------+
| id                    | int(11)      | NO   | PRI | NULL    | auto_increment |
| fk_issue              | int(11)      | YES  |     | NULL    |                |
| n_status_id           | int(11)      | YES  |     | NULL    |                |
| dt_published_datetime | datetime     | YES  |     | NULL    |                |
| dt_offline_date       | datetime     | YES  |     | NULL    |                |
| dt_created_date       | date         | YES  |     | NULL    |                |
| n_publisher_id        | int(11)      | YES  |     | NULL    |                |
| created_at            | datetime     | YES  |     | NULL    |                |
| updated_at            | datetime     | YES  |     | NULL    |                |
| page_name             | varchar(255) | YES  |     | NULL    |                |
+-----------------------+--------------+------+-----+---------+----------------+
10 rows in set (0.00 sec)

Here is the model

class Page < ActiveRecord::Base
  has_many :slots, :dependent => :destroy
  accepts_nested_attributes_for :slots

  #attr_accessor :n_publisher_id
  #attr_accessible :n_publisher_id
end

Create Action

  def create
    page = Page.new(params[:page].merge({:n_publisher_id => 1}))
    #page.dt_created_date = Date.today

    page.n_publisher_id = 1

    respond_to do |format|
      if page.save
        format.html { redirect_to(page, :notice => 'Page was successfully created.') }
        format.xml  { render :xml => page, :status => :created, :location => page }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => page.errors, :status => :unprocessable_entity }
      end
    end
  end
A: 

Did you verify already that session[:n_publisher_id] has a value != nil?

A quick verification in your controller, try:

def create
    page = Page.new(params[:page])
    page.n_publisher_id = 3
end

If all the newly created pages have n_publisher_id == 3, then session[:n_publisher_id] == nil and must be set somewhere in your app.

Yannis
Hello. I tried this and the saved records still show n_publisher_id as NULL. This is confusing... do I need a hidden field in the form?
nktokyo
Are you sure that you have a n_publisher_id column in your pages table?
Yannis
Hello, I pasted the schema above
nktokyo
Have you added :n_publisher_id to attr_accesible in your model?
Yannis
No, I only had attr_accessor :n_publisher_id. I added attr_accessible and it did not make any difference.
nktokyo
Remove both your attr_accessible and attr_accessor lists (and the attr_protected one if it exists)
Yannis
removed. It saves through console now, but not through web app
nktokyo
+2  A: 

You should never overwrite the initialize method of your ActiveRecord object. Rails is doing a bunch of stuff behind the scenes and it's known to mess things up.

Instead just append your attribute onto your initial params that you're passing in.

So, assuming :n_publisher_id is a real attribute of your AR object (column in the table), something like:

@page = Page.new(params[:page].merge({:n_publisher_id => session[:n_publisher_id]}) 

should work.

This also assumes that session[:n_publisher_id] is also not nil (otherwise, of course it will be saved as nil in the db)

brad
Hello. I tried this and the value is still not being set. "page = Page.new(params[:page].merge({:n_publisher_id => 1}))"
nktokyo
Can you show us the db schema as taken from schema.rb ?? If you do, on the command line, Page.new(:n_publisher_id => 1).save does it work? If not then the only reason can be that n_publisher_id is NOT actually part of the db schema.
brad
Just to add to that. Creating a attr_accessor on your class is not the same as actually having that attribute be persistent in the db. It needs to happen when you created the class, likely with a migration. Or you need to update that db table to have the correct column
brad
Hi Brad. The schema is added to the original post.
nktokyo
Page.new(:n_publisher_id => 1) works in the console. I see => #<Page id: nil, fk_issue: nil, n_status_id: nil, dt_published_datetime: nil, dt_offline_date: nil, dt_created_date: nil, n_publisher_id: 1, created_at: nil, updated_at: nil, page_name: nil>
nktokyo
@nktokyo: I bet that if you also save that object in console and then reload it from db, it will have `nil` value. Try `p = Page.new(:n_publisher_id => 1); p.save; p.reload` and see what happens.
klew
you're correct... infact now the new action doesn't even set the n_publisher_id field... >> Page.new(:n_publisher_id => 1)=> #<Page id: nil, fk_issue: nil, n_status_id: nil, dt_published_datetime: nil, dt_offline_date: nil, dt_created_date: nil, n_publisher_id: nil, created_at: nil, updated_at: nil, page_name: nil>confused :(
nktokyo
@nktokyo: please add your model code to question
klew
sure, added now. thanks
nktokyo
I didn't notice the attr_accessor before. I would assume after removing it this should work fine. You don't need to create accessors (and don't want to) for active_record objects unless you need to override with custom behaviour. In any case setting the instance var @n_publisher_id is not the same as attributes[:n_publisher_id] So this still isn't working with your above code?
brad
figured it out now. I have the controller in sub-folder in an admin module (controllers/admin/pages_controller) but it was calling the function in controllers/pages_controller. Not sure how to force the save operation to use the controller in the admin folder. Thanks for all the help on this both of you. I learned a lot!
nktokyo
A: 

It sounds like session[:n_publisher_id] is nil. Or you are overwriting it somewhere.

If you have the value available in the create action, merge in the params there and you don't need to bother setting it in the new action.

If you only have it available in the new action for some reason, use a hidden field

My gut tells me that you should be setting this explicitly and actually not allowing mass assignment, but I don't know your use case.

Tony
I want to set it from a session variable, who was the user logged in that did this action. I'm trying to set it to a number at first... and not getting very far
nktokyo
i think you'll have to be more specific about your error for help. for example, post the request from the rails log, then the controller code that processes that request, and finally the model code for the object being built. with the information you have provided, i think every person who answered has provided good insight
Tony
+1  A: 

Remove attr_accessor :n_publisher_id from your model. It is column in db, so Rails took care for it. Maybe your attr_accessor overrides something.

klew
Sorry, I thought this was fixed. It's not. After removing the attr_accessor I was able to make and save correctly through the console. But not through the web app. Neither of the following sets the fieldpage = Page.new(params[:page].merge({:n_publisher_id => 1}))orpage = Page.new(params[:page])page.n_publisher_id = 1
nktokyo
Can you show your logs for `create` action?
klew
Page Create (0.2ms) INSERT INTO `pages` (`fk_issue`, `dt_created_date`, `created_at`, `updated_at`, `n_status_id`, `n_publisher_id`, `dt_offline_date`, `page_name`, `dt_published_datetime`) VALUES(NULL, NULL, '2010-10-01 14:46:58', '2010-10-01 14:46:58', NULL, NULL, NULL, 'hello', NULL)
nktokyo
Ok, so it is not saving it. Can you add whole `create` action to your question?
klew
Added - you see I'm trying to set the field two ways, removing either of them or leaving both sets same result
nktokyo
Last two ideas: try using instance variable instead of local variable (rename `page` to `@page`), and second idea: restart your server (sometimes it helps). You can also try adding `logger.debug @page.inspect` in `create` action before saving and see in log if this value is set.
klew
no luck. I had tried both earlier actually. I assume this is supposed to work without needing a hidden field that I update with JS or something, right? Thanks for your help
nktokyo
If you assign in `new` action then you need `hidden_field`, but it is bad idea, because anyone can change this value and submit whatever they want.
klew
right, so I want to do in create/update. Bizarre
nktokyo