rails pass variable to model from controller not working - ruby-on-rails

Im trying to pass a variable from controller to my form to no avail.
Its working in another controller but cannot make it work for new user registrations.
def update
#profile = Profile.find(params[:id])
#profile.form = "signup"
...
end
Inside model I can do #profile.form to get the value
This does not work for new user registrations:
inside create action:
undefined method `form=' for nil:NilClass
how to pass a variable to my model upon new user registration? User = User.new then #user.form == "signup" does not work either, i have :form in my attributes accessible list
Part of model:
attr_accessible form
...
validates :city_id, :presence => true, :if => :signup?
def signup?
##profile.form == "signup"
##user.form == "signup"
if self.form == "signup"
return true
else
return false
end
end
EDIT 1:
Still unable to pass a param to the model :S:S:S tried every possible way and google found solution.
The create method for my registrations#create =
def create
profile = Profile.new
profile.form = "signup"
super
end

I am not sure what exactly your problem is .
What I understand after I read your problem statement twice is that you tried to "new" a instance of Profile, assign its form attribute. And use its instance method signup? to do validation. But you get an error after on self.form because self reference to the nil Class
I think you should change profile to #profile inside the create method.
Just by guess after reading ruby guide about instance variable,
My thought is that declaring the instance variable that will be added dynamically inside the controller structure and later they are passed to the model. And it is always #... inside controller generated by rails g scaffold.
Just give it a try :)

Interesting. I believe what you want to do is have a virtual attribute 'form' of an object a certain value. I.e. does form exist in the database as well. If it doesn't you should be using attr_accessor :form
Documentation
This defines the getter and setter method for form in the class where it is being invoked.
However, the error you stated is something radically different.
undefined method `form=' for nil:NilClass
This merely means a profile with the id being passed in the params does not exist. i.e. if we are updating params id = 222, a database record with id 222 does not exist for Profile.

Related

Mass assignment, nested form and current user as author

I have a couple of objects, foo, bar and user.
I have a form for creating a new foo object, which uses simple_fields_for and accepts_nested_attributes_for to create a new child bar object at the same time.
Now, I want to set the current_user as the author attribute for the new bar, but I can't figure out how best to do this. (still new to Rails.)
I have tried the following in my create method within the foo controller:
def create
#foo = Foo.build(params[:foo])
#foo.bars.find(:first).author = current_user
However when I run this I get an exception.
undefined method `author=' for nil:NilClass
Can anyone offer any advice on how best to go about this?
You likely need to build the Bar object under #foo. ie
def new
#foo = Foo.new
#foo.bars.build
end
def create
#foo = Foo.new(params[:foo])
#foo.bars.first.author = current_user
if #foo.save
redirect_to #foo
else
render action: "new"
end
end
A good resource for nested forms: http://railscasts.com/episodes/196-nested-model-form-part-1?view=asciicast
Provided you set accepts_nested_attributes_for in your model and correctly used fields_for in your form, params[:foo] will contain an element called bar_attributes that will contain the data entered on the form about the bar object. Look through the railcast I linked to for more info.

access controller's object attributes in view page in ROR

I am new to ROR and learning it. In my controller I have an admins
record and I am passing that admin object to the admin's view page to
get the name of the admin. But when I try to access the name it
showing a error:
undefined method 'name' for :current_admin:Symbol
Please help..
Please find my code below
Sessions Controller
def create
admin=Admin.find_by_email(params[:session][:email].downcase)
if admin && admin.authenticate(params[:session][:password])
redirect_to(admins_index_path(:current_admin=>admin))
end
end
In view page of index_admin
In your action for index_admin you need to get an admin object from your param. The value of a param is usually just a string.
def create
admin=Admin.find_by_email(params[:session][:email].downcase)
if admin && admin.authenticate(params[:session][:password])
redirect_to(admins_index_path(:current_admin => admin.id)) # pass the id, not the object
end
end
def index_admin
#current_admin = Admin.find(params[:current_admin])
end
In you index_admin.html.erb:
Hi <%= #current_admin.name %>

Rspec Rails: testing controller method 'create' with a multi-model form

I am building a Ruby on Rails app with the usual assortment of models, views and controllers.
The 'create' action in one of my controllers is supposed to create an instance of two different models. Here's my code:
def create
#league = League.new(params[:league])
#user = #league.users.build(params[:user])
... .save conditions appended ...
end
So, when you call 'create' through the LeaguesController via a POST request to /leagues, you get a new instance of League and a new instance of User. I also want the new User instance to inherit the ID of the new League instance, so it can be used as the foreign key to link the instances together. This is accomplished with:
def create
#league = League.new(params[:league])
#user = #league.users.build(params[:user])
#league_id = #league.id
#user.update_attribute('league_id', #league_id)
... .save conditions appended ...
end
The User model already belongs_to the League model, which has_many users.
The above code works just fine and dandy, verified via manual testing. However, I can't for the life of me figure out how to automate these tests with Rspec. I'm trying to be a good boy and use test-driven design, but this has me stumped.
The issue is that I can't figure out how to access the attributes of the newly created instances of League and User in my tests. I am attempting to do so using the following code:
describe LeaguesController do
describe 'new league and user' do
it 'should create a new user with a league_id equal to the new leagues id'
#league_attr = { :name => "myleague", :confirmation_code => "mycode", :id => 5}
#user_attr = { :username => "myname", :password => "mypass"}
post :create, :user => #user_attr, :league => #league_attr
assigns(:league_id).should eql(5)
end
end
end
But the test returns nil for the value of :league_id
I'm new to both programming in general and Rspec in particular, so I really appreciate any help someone might offer!
You cannot assign :id with new. Try this:
def create
#league = League.new(params[:league])
#league.id = params[:league][:id] if params[:league][:id]
#user = #league.users.build(params[:user])
#league_id = #league.id
#user.update_attribute('league_id', #league_id)
... .save conditions appended ...
end
That said, I wonder how come it works in the browser.
Also, you better off using FactoryGirl or Fixtures to assign data to models when testing.
Have you tried pry?
Whenever I discover something like this I find it very handy to be able to insert a brakepoint via Pry (or Ruby-Debug) so I can inspect the variables and their behavior.
I suspect putting in a binding.pry between #league_id = #league.id and #user.update_attribute('league_id', #league_id) may very well shed some light on the issue.
Also note that user will automatically inherit the #league_id when you persist it via the #league.save call. (that's the idea behind #league.users.build(..) - it will set the required relationships correctly upon persistance.

How to set a Rails model's instance properties with a method call?

I have a controller that instantiates a model and then calls a method to build associations. I tried to use this method to also set the properties of the model, but it didn't work and I'm wondering why.
here is my code:
#my controller
user = User.new
user.apply_omniauth(omniauth)
debugger
#my model
def apply_omniauth(omniauth)
email=omniauth["extra"]["user_hash"]["email"]
name=omniauth["extra"]["user_hash"]["name"]
authentications.build(:provider => omniauth['provider'],:uid => omniauth['uid'])
end
#irb
rails:6ree-1.8.7-2010.02 > user.name
=> nil
When I set the properties from the controller, then it worked.
Try:
self.name=omniauth["extra"]["user_hash"]["name"]
The way you are setting name is actually setting a local variable called name in the apply_omniauth method. It's not a reference to the name attribute of the model. To assign to the model's name attribute, you need to access it using self.name

undefined method error, but I defined it!

Rails newbie here, trying to get a new controller working.
When I try to show ann existing instance, I get an undefined method error on a helper method.
Code follows.
Any idea why getRecipes would be undefined?!
Controller:
def show
id = params[:id]
recipe_ids = ConcreteMenu.getRecipes(id)
respond_to do |format|
format.html
end
end
Model
require 'json/objects'
class ConcreteMenu < ActiveRecord::Base
has_many :menu_recipes
has_many :recipes, :through => :menu_recipes
belongs_to :menu
def self.getRecipes(id)
recipes = MenuRecipe.find(:all, :conditions => {:concrete_menu_id => id}, :select => 'id')
end
end
It would help if you pasted the error text, because your explanation leaves a lot of possibilities for what could be wrong. BUT, there is an easier way to get what you want. The value of defining "has_many" relationships is that instead of calling a class method and passing the id of a concrete menu to get its associated recipes, you can just do this:
def show
#concrete_menu = ConcreteMenu.find(params[:id], :include => :recipes)
end
Now you'll have the menu object, and #concrete_menu.recipes returns an array of recipes you need. This feature is already built in, no need to reinvent the wheel.
Also, I noticed you were attempting to collect id's in the controller instead of the objects themselves. This suggests that you're going back and actually retrieving the records in the view itself. This is less efficient, and more difficult to troubleshoot when things go wrong. My example above will do what you need in a better (and more rails-accepted) way.
As you have it defined there, it should be available. Is there a chance you have something else called ConcreteMenu defined, but in a different context?
To be sure you're calling the correct one, where there may be ambiguity, you can refer to the top-level class:
recipe_ids = ::ConcreteMenu.getRecipes(id)
The other way to check that the method is defined correctly via script/console:
ConcreteMenu.methods.grep(/getRecipe/)
# => ["getRecipes"]
This is presuming, of course, you're having trouble with the getRecipes method. There's a possibility you're mistaking how controller variables are passed to the view:
def show
#id = params[:id]
#recipe_ids = ConcreteMenu.getRecipes(#id)
respond_to do |format|
format.html
end
end
Any instance variables defined (#...) will be available within the context of the view, but any local variables will no longer be defined as they are out of scope.

Resources