NoMethodError on collection_select input - ruby-on-rails

I have been trying different things to fix this and it's driving me nuts...
I have an input field:
<%= collection_select(:stakeholder, :user_id, User.all, :id, :first_name) %>
Each stakeholder has a user_id attribute, which is an integer.
When I try to render the form, I get this NoMethodError:
undefined method `id' for 2:Fixnum
Any ideas?
Edit: adding full form view
<%= simple_form_for([#project, #stakeholder]) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :first_name %>
<%= f.input :last_name %>
<%= f.input :email %>
<%= f.input :address %>
<%= f.input :city %>
<%= f.input :sentiment, %>
<%= f.label :tags, "Tags (separated by commas)" %>
<%= collection_select(:stakeholder, :user_id, User.all, :id, :first_name) %>
<%= f.button :submit %>
</div>
user.rb
class User < ActiveRecord::Base
belongs_to :account
has_many :stakeholders
def set_default_role
self.role ||= :user
end
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :invitable, :database_authenticatable, :registerable, :confirmable,
:recoverable, :rememberable, :trackable, :validatable
end
stakeholder.rb
class Stakeholder < ActiveRecord::Base
belongs_to :project
has_many :notes
belongs_to :user
acts_as_taggable
def full_name
full_name = "#{first_name.capitalize} #{last_name.capitalize}"
end
end

Take a look at this documentation.
collection_select(object, method, collection, value_method,
text_method, options = {}, html_options = {}) public
Returns <select> and <option> tags for the collection of existing
return values of method for object's class. The value returned from
calling method on the instance object will be selected.
You seem to have an extra argument in your collection_select tag which is causing Rails to call :id as a method when it's actually a number (2).
user_id is a field in some Stakeholder object, right? So unless I'm misunderstanding how you've set up your relationships, stakeholder isn't relevant (in the sense that all you want is a user ID from your form).
This line should get you what you want.
<%= f.collection_select(:user_id, #users, :id, :first_name)

Related

Create devise user and profile model with same form in rails

I'm looking to create a form with input fields for two models - Devise User model and Profile model. I want the profile model to be created with the fields and reference the User model when created.
Registration New view
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<!-- Devise Fields for User model -->
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
<%= f.password_field :password, autocomplete: "new-password" %>
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
<!-- Profile model -->
<%= f.fields_for :profile do |g| %>
<%= g.text_field :first_name %>
<%= g.text_field :last_name %>
<% end %>
<%= f.submit "Sign up" %>
<% end %>
User Model
has_one :profile, dependent: :destroy
attr_accessor :first_name, :last_name
accepts_nested_attributes_for :profile
Profile Model
belongs_to :user
Application Controller
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [ profile_attributes: [:first_name, :last_name]])
end
Devise Registration controller (override)
def new
super do |resource|
resource.build_profile
end
end
After filling out the form I receive an error message. Refer to the following image
Here is the code on Github https://github.com/Goeken/Speech-today
How should I go about this?
I had look into your github repository code & I found that your User model code is not correct. Here's the modified user model -
class User < ApplicationRecord
has_one :profile, dependent: :destroy
# You should not add first_name last_name validation message here,
# because those are profile model attributes, Not user model
#validates_presence_of :first_name, :last_name
accepts_nested_attributes_for :profile
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
And rest of code are OK.
I hope it will work.

RoR NoMethodError in Credits#new

Hi,
I am doing my homework around the building a simple RoR app and got stuck with the following:
I created a Scaffold called "Credit", and a relationship between the User and Credit model:
Here are my files
credit.rb
class Credit < ActiveRecord::Base
attr_accessible :amount, :user_id
belongs_to :user
belongs_to :merchant
end
user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me,
:first_name, :last_name, :profile_name
# attr_accessible :title, :body
has_many :statuses
has_many :merchants
has_many :credits
def full_name
first_name + " " + last_name
end
end
When trying to create a new credit entry with the following form:
<%= simple_form_for(#credit) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :amount %>
<%= f.input :user_id, collection: User.all %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
I get the following error,
NoMethodError in Credits#new
Showing/Users/andreucasadella/rails_projects/monedero/app/view credits/_form.html.erb where line #6 raised:
undefined method `user_id' for #
Any idea?

rails devise user external api

I am trying to setup a newsletter signup procedure when a new user signs up. I am using Mailchimp via gibbon to handle the newsletters. I have added a subscribe attribute to my model and a getter and setter method. I also have added the subscribe checkbox to my form. What I need to do is if the form box is checked subscribe the user to the email on creation.
model
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :username, :subscribe
validates :username, presence: true
validates_uniqueness_of :username
has_many :contest_entries, dependent: :destroy
has_many :votes, dependent: :destroy
def subscribe=(join)
puts "called subscribe with #{join}"
if join
Gibbon.new.list_subscribe(:id => "blah", :email_address => self.email)
end
end
def subscribe
subscribe ||= false
end
end
Form view
<h2>Sign up</h2>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<p><%= f.label :username %><br />
<%= f.text_field :username %></p>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.label :subscribe, "Subscribe to Newsletter?" %><br />
<%= f.check_box :subscribe, :checked => true %></div>
<div><%= f.submit "Sign up" %></div>
<% end %>
<%= render "devise/shared/links" %>
I was hoping that by adding the attr_accessible and a method it would call the api from the contoller automatically, but it does not seem to be called.
Any advice on how to handle this? I could also use advice on how to test with RSPEC to make sure it is being called.
Thanks,
Cory
Ok I figured out the issue. The problem was with the check for join inside the setter method. Since it was a checkbox, I needed to check for a matching integer of 1.
def subscribe=(join)
begin
if join.to_i == 1
gb = Gibbon.new
result = gb.list_subscribe(:id => "blah", :email_address => self.email)
end
rescue
false
end
end

can't mass assign nested attributes

I've checked a few answers to similar problems, and all seem to suggest the problem is attr_accessible, but I just can't seem to get this working.
Basically I have User & Address model,and want to assign Address attributes as nested attributes. But when I save it causes the can't mass-assign attributes error shown below.
I've tried many variations of attr_accessible in below code, like :addresses_attributes, :address_attributes, :primary_address_attributes...I'm not sure why it's not working,perhaps because it's in the Member module declaration??
Can anyone help?
class Member::User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# each user may have zero or many addresses
# their primary email is also set as their login id.
has_many :addresses
has_one :address, :class_name => "Member::Address", :conditions => "is_primary = true"
accepts_nested_attributes_for :addresses, :address
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :address_attributes
validates_presence_of :email
end
My form that submits the nested fields (relevant parts of)
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => {:class => "form-horizontal"}) do |f| %>
<small>Mandatory fields marked *</small><br><br>
<% devise_error_messages! %>
<% flash.each do |name, msg| %>
<div class="alert alert-<%= name == :notice ? "success" : "error" %>">
<a class="close" data-dismiss="alert">×</a>
<%= msg %>
</div>
<% end %>
<%= f.fields_for resource.build_primary_address do |address_form| %>
<div class="control-group">
<%= address_form.label :first_name, :class => "control-label" %>
<div class="controls">
<%= address_form.text_field :first_name, :class => "input-xlarge" %>
</div>
</div>
<div class="control-group">
<%= address_form.label :last_name, :class => "control-label" %>
<div class="controls">
<%= address_form.text_field :last_name, :class => "input-xlarge" %>
</div>
</div>
<% end %>
The error shows this:
Can't mass-assign protected attributes: member_address
{"utf8"=>"✓",
"authenticity_token"=>"HrZJG2krn15veUKJVh6PgEs4wwufaeRhciHcUIn6AaM=",
"user"=>{"member_address"=>{"first_name"=>"asdf",
"last_name"=>"asdfsafd"},
"email"=>"Bob.JOnes#jones.com",
"password"=>"[FILTERED]",
"password_confirmation"=>"[FILTERED]"}}
In order for rails to understand that that the primary address being submitted in the form is a nested attribute, you have to explicitly tell it the relation here:
<%= f.fields_for :address, resource.build_primary_address do |address_form| %>
. The reason is, because your model names are scoped with Member::, and rails derives form parameter names from the class names, in your params hash you end up with :member_address instead of :address. Because :address in this case is a field for which :user accepts nested attributes, :address should be represented as :address_attributes in the params hash, so make sure the latter appears in attr_accessible.
Add
attr_accessible :member_address
to the User model.
Explanation: every hash key that you want to initialize an ActiveRecord instance with must be stated as attr_accessible. Looking at your hash keys there is:
"user"=>{"member_address"=>{ ... }}
member_address key in the hash which initializes the User instance, thus it has to be included in the attr_accessible statement.

rails devise: user and account model

Hi I am trying to customize the sign up page by adding an additional field, name.
This is done by adding a Profile model to my app.
class Profile < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :profile_attributes
has_one :profile, :dependent => :destroy
accepts_nested_attributes_for :profile
end
I overrode the registration model:
# app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def new
super
profile = #user.build_profile
end
def create
super
end
def update
super
end
end
And my new sign up page:
<h2>Sign up</h2>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<div><% f.fields_for :profile do |builder| %>
<p><%= builder.label :name %></p>
<p><%= builder.text_field :name %></p>
<% end %></div>
<div><%= f.submit "Sign up" %></div>
<% end %>
<%= render "links" %>
However, I am not sure if everything else works, but the registration page still looks the same. That is, it doesn't show the name input field. How do I fix this?
What am I missing?
I suspect you did not generate the views. Did you run the following?
rails generate devise:views
More information on changing views can be found in "Configuring views" on the devise wiki:
https://github.com/plataformatec/devise
Thanks,
Tabrez

Resources