Couldn't find Photo with id=16 - ruby-on-rails

Not sure why this isn't working but I've been mis-guided I think....I'd rather not re-route but simply have the photo uploaded in the current landing_welcome page.. not be transfered to an update template.
error:
Couldn't find Photo with id=16 [WHERE "photos"."attachable_id" = $1 AND "photos"."attachable_type" = $2]
def update
#user = current_user.photos.find(params[:id])
#user.update_attributes!(person_params)
redirect_to #user
end
Users_controller.rb
class UsersController < ApplicationController
def update
#user = current_user.photos.find(params[:id])
#user.update_attributes!
redirect_to #user
end
def show
end
end
landing_welcome.html.erb
<div class="tab-pane" id="tab2">
<%= nested_form_for current_user, :html=>{:multipart => true } do |f| %>
<%= f.fields_for :photos do |p| %>
<p>
<%= image_tag(p.object.file.url) if p.object.file? %>
<%= p.label :file %><br />
<%= p.file_field :file %>
</p>
<%= p.link_to_remove "Remove this attachment" %>
<% end %>
<%= f.link_to_add "Add photos to your profile", :photos %>
<br /><br />
<p><%= f.submit %></p>
<% end %>
</div>
routes.rb
root to: "home#landing"
devise_for :users, :controllers => {:registrations => "users/registrations",
:sessions => "users/sessions",
:passwords => "users/passwords"}
get "welcome", to: "home#landing_welcome"
devise_scope :user do
# get "edit/edit_account", :to => "devise/registrations#edit_account", :as => "account_registration"
get 'edit/edit_account' => 'users/registrations#account_registration', as: :edit_account
end
patch '/users/:id', to: 'users#update', as: 'user'
photo.rb
class Photo < ActiveRecord::Base
attr_accessible :file
belongs_to :attachable, :polymorphic => true
mount_uploader :file, FileUploader
end
user.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email,
:password,
:password_confirmation,
:zip,
:gender,
:remember_me,
:first_name,
:last_name,
:birthday,
:current_password,
:occupation,
:address,
:interests,
:aboutme,
:profile_image,
:photos_attributes
has_many :photos, as: :attachable
accepts_nested_attributes_for :photos
mount_uploader :profile_image, ProfileImageUploader
validates :gender, :presence => true
def number_of_users
User.all.count
end
end

For lack of a better answer, I think your woes lie in the query generated by your app:
Couldn't find Photo with id=16 [WHERE "photos"."attachable_id" = $1 AND "photos"."attachable_type" = $2]
Two factors are present here:
Why is your attachable_id being called as $1?
Why is your attachable_type a number, not a string?
Polymorphic Association
Your query is trying to load a Photo with ID=16, however, your query is also trying to validate the model, to satisfy the polymorphic association. This is where the error is coming from
As you've not stated which route / page this error is showing, I can only speculate as to the cause of the problem:
#user = current_user.photos.find(params[:id])
This query is really bad for a number of reasons:
You're using the current_user object directly. I might be wrong here, but this is used by Devise / Warden to store relative information about the logged-in user, and is not a real ActiveRecord object (with relational data etc)
You're trying to .find on top of a relation (current_user.photos)
Although this might be incorrect, I would look at doing this for that query:
#photo = User.joins(:photos).find(current_user.id).where("photos.id = ?", params[:id])
Then you can perform the updates you require

Related

NoMethodError in Pages#profile

I'm working on build a Twitter-like sample app, but I am stuck at creating a following method. I have created a Relationship model and the necessary classes to accomplish the task, but when I load the page, I receive the error "NoMethodError" on this line: <%= form_for(current_user.active_relationships.build, remote: true) do |f| %>
I render the form on the profile page like so:
<%= render '/components/follow_button', :user => User.find_by_username(params[:id]) %>
Here is the form:
<% if current_user.id != user.id %>
<div class="col s12">
<div class="panel panel-default">
<% if !current_user.following?(user) %>
<%= form_for(current_user.active_relationships.build, remote: true) do |f| %>
<div><%= hidden_field_tag :followed_id, user.id %></div>
<%= f.submit "Follow", class: "btn btn-primary" %>
<% end %>
<% else %>
<%= form_for(current_user.active_relationships.find_by(followed_id: user.id),
html: { method: :delete }) do |f| %>
<%= f.submit "Unfollow", class: "btn" %>
<% end %>
<% end %>
</div>
</div>
<% 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
validates_uniqueness_of :email, :case_sensitive => false
validates_uniqueness_of :username, :case_sensitive => false
has_many :posts, dependent: :destroy
has_many :active_relationships, class_name: "Relationship", foreign_key: "follower_id", dependent: :destroy
has_many :passive_relationships, class_name: "Relationship", foreign_key: "followed_id", dependent: :destroy
has_many :following, through: :active_relationships, source: :followed
has_many :followers, through: :passive_relationships, source: :follower
def follow(other)
active_relationships.create(followed_id: other.id)
end
def unfollow(other)
active_relationships.find_by(followed_id: other.id).destroy
end
def following?(other)
following.include?(other)
end
end
Relationship.rb
class Relationship < ActiveRecord::Base
belongs_to :follower, class_name: "User"
belongs_to :followed, class_name: "User"
validates :follower_id, presence: true
validates :followed_id, presence: true
end
RelationshipsController:
class RelationshipsController < ApplicationController
def create
user = User.find(params[:followed_id])
current_user.follow(user)
redirect_to(:back)
end
def destroy
user = Relationship.find(params[:id]).followed
current_user.unfollow(user)
redirect_to(:back)
end
end
Any help would be greatly appreciated.
EDIT: Following method used in Routes.rb
devise_for :users
resources :users do
member do
get :following, :followers
end
end
On the form_for documentation, it eventually talks about 'Resource-oriented style' forms
In the examples just shown, although not indicated explicitly, we still need to use the :url option in order to specify where the form is going to be sent. However, further simplification is possible if the record passed to form_for is a resource, i.e. it corresponds to a set of RESTful routes, e.g. defined using the resources method in config/routes.rb. In this case Rails will simply infer the appropriate URL from the record itself
<%= form_for(Post.new) do |f| %>
...
<% end %>
is equivalent to something like:
<%= form_for #post, as: :post, url: posts_path, html: { class: "new_post", id: "new_post" } do |f| %>
...
<% end %>
Looking at your code, since you are not passing a :url option to form_for and you are passing an instance of a model, it's assuming your model was configured in the routes file with resources :relationships, which generates some named route helpers such as relationships_path, the method that it's complaining is missing.
To fix your problem, you need to pass form_for a :url where your controller lives and where it should post to, or update your routes to use the resources :relationships. You can read more information about the resources routing here. If you add
resources :relationships, only: [:create, :destroy]
outside of your devise_for block, you'll end up with 2 new routes for
Prefix Verb URI Pattern Controller#Action
relationships POST /relationships(.:format) relationships#create
relationship DELETE /relationships/:id(.:format) relationships#destroy
and the named helpers relationships_path and relationship_path which your 2 form_for tags are going to be looking for.
Don't forget to restart your server after making changes to your config/routes.rb file to make sure rails picks them up.

Devise: Could not find a valid mapping for User id

The following form in a partial called locationpicker:
<%= simple_form_for(current_user, url: registration_path(current_user), method: :put ) do |f| %>
<% f.association :location, collection: Location.where(category: 'Country'), label: false, input_html: {onchange: "this.form.submit()"} %>
<% end %>
brings up this error:
Could not find a valid mapping for #<User id:...
It's the registration_path(current_user) which is causing it. My suspicions were that something has changed in the routes or the users model, but I can't for the life of me think what or know where to start looking. I thought it might be the recent inclusion of ActiveModel::Dirty but removing that doesn't solve the problem.
Routes.rb:
scope ":locale", locale: /#{I18n.available_locales.join("|")}/ do
devise_for :users, :controllers => {:registrations => "registrations"}
...
end
User.rb
class User < ActiveRecord::Base
include ActiveModel::Dirty
devise :database_authenticatable, :registerable, #:encryptable,
:recoverable, :rememberable, :trackable, :validatable, :lockable
has_one :assignment
has_one :role, :through => :assignment
has_many :changerequests, inverse_of: :created_by, foreign_key: "created_by_id"
belongs_to :location, required: true
belongs_to :person, inverse_of: :user, required: true
has_many :people_details, through: :person
scope :inclusive, -> {includes(:person).includes(:people_details).includes(:location).includes(:assignment).includes(:role)}
after_update :update_locale
after_save :expire_caches
def role?(role_sym)
role_name.to_sym == role_sym
end
def role_group?(role_sym)
role_group_name.to_sym == role_sym
end
def send_on_create_confirmation_instructions
true
end
def update_locale
if locale_changed?
I18n.locale = self.locale || "en"
self.expire_caches
end
end
def country
if self.location.category == "Country"
self.location
elsif self.location.ancestors.where(category: "Country")
self.location.ancestors.where(category: "Country").first
elsif self.location.children.where(category: "Country")
self.location.children.where(category: "Country").first
end
end
def expire_caches
#Admin users can change their location so the caches need expiring
if location_id_changed? or locale_changed?
ctrlr = ActionController::Base.new
#Clear fragments
ctrlr.expire_fragment("#{id}_#{locale}_location_picker")
etc...
end
if location_id_changed?
#Clear other caches
Rails.cache.delete("#{id}_locations_scope")
.... etc
end
end
Try adding as: in your simple_form_for call:
<%= simple_form_for(current_user, as: :user, url: registration_path(current_user), method: :put ) do |f| %>
<% f.association :location, collection: Location.where(category: 'Country'), label: false, input_html: {onchange: "this.form.submit()"} %>
<% end %>
Normally, the devise registrations edit form looks like:
= simple_form_for(resource, as: resource_name, url: user_registration_path, html: { method: :patch }) do |f|
In other words, using "resource" not "current_user". You might try that as well, if your form partial is being rendered within the devise controller context.

Rails + Devise Nested Registration form undefined method 'build_address'

Hi this question is basically the same as this one, which had no responses. I'm trying to combine the Devise registration form to include fields that produce not only a "user", but a "customer" object, an "account" object for that customer, and an "address" for that customer.
When visitor clicks "Sign Up", the registration form should include the standard Devise stuff, but also the fields for the creation of the other objects. Instead, I get this error:
NoMethodError in Registrations#new
undefined method `build_address' for #
Extracted source (around line #6):
<div class="panel panel-default" style="width: 14em;">
<% resource.build_customer if resource.customer.nil? %>
<% resource.build_account if resource.accounts.nil? %>
<% resource.build_address if resource.address.nil? %>
<%= form_for(resource, as: resource_name, url: >registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<h3>User Info</h3>
Rather than explaining all the relationships, here are the models:
user.rb
class User < ActiveRecord::Base
before_create :generate_id
# Virtual attribute for authenticating by either username or email
# This is in addition to a real persisted field like 'username'
attr_accessor :login
has_one :administrator
has_one :customer
has_many :accounts, through: :customer
accepts_nested_attributes_for :customer, :allow_destroy => true
accepts_nested_attributes_for :accounts, :allow_destroy => true
has_one :address, through: :customer
accepts_nested_attributes_for :customer, :allow_destroy => true
accepts_nested_attributes_for :address, :allow_destroy => true
validates_uniqueness_of :email, :case_sensitive => false
validates_uniqueness_of :id
validates :username,
:presence => true,
:uniqueness=> {
:case_sensitive => false
}
# User ID is a generated uuid
include ActiveUUID::UUID
natural_key :user_id, :remember_created_at
belongs_to :user
# specify custom UUID namespace for the natural key
uuid_namespace "1dd74dd0-d116-11e0-99c7-5ac5d975667e"
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :timeoutable, :recoverable, :trackable, :validatable
# Generate a random uuid for new user id creation
def generate_id
self.id = SecureRandom.uuid
end
# Allow signin by either email or username ("lower" function might have to be removed?)
def self.find_for_database_authentication(warden_conditions)
conditions = warden_conditions.dup
if login = conditions.delete(:login)
where(conditions.to_h).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first
else
where(conditions.to_h).first
end
end
end
customer.rb
class Customer < ActiveRecord::Base
belongs_to :user
has_one :address
has_many :accounts
validates :phone1, :firstname, :lastname, presence: true
end
account.rb
class Account < ActiveRecord::Base
belongs_to :customer
belongs_to :user
has_one :acct_type
has_many :acct_transactions
validates :acct_type, presence: true
end
address.rb
class Address < ActiveRecord::Base
belongs_to :customer
belongs_to :user
validates :zip_code, presence: true
validates :address1, presence: true
has_one :zip_code
has_one :state, through: :zip_code
end
The two controllers in question:
registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
before_filter :configure_permitted_parameters
# GET /users/sign_up
def new
#user = current_user
#customer = nil ##user.customer
#account = nil ##customer.account
#address = nil ##customer.address
# Override Devise default behavior and create a customer, account, and address as well
build_resource({})
resource.build_customer
respond_with self.resource
build_resource({})
resource.build_account
respond_with self.resource
build_resource({})
resource.build_address
respond_with self.resource
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u|
.permit(:username, :email, :password, :password_confirmation,
:customer_attributes => [:phone1, :phone2, :title, :firstname, :lastname],
:account_attributes => :acct_type,
:address_attributes => [:address1, :address2, :zip_code])
}
end
end
addresses_controller.rb (The important parts)
def new
#customer = current_user.customer
#address = #customer.address.build(:customer_id => #customer.id,
:address1 => nil,
:address2 => nil,
:zip_code => nil)
end
def create
#customer = current_user.customer
#address = #customer.address.build(:customer_id => #customer.id,
:address1 => nil,
:address2 => nil,
:zip_code => nil)
respond_to do |format|
if #address.save
format.html { redirect_to #address, notice: 'Address was successfully created.' }
format.json { render :show, status: :created, location: #address }
else
format.html { render :new }
format.json { render json: #address.errors, status: :unprocessable_entity }
end
end
end
And here is the view where the exception is raised (It's really long so actually the important parts):
<h1>Create an account</h1>
<div class="form-group">
<div class="panel panel-default" style="width: 14em;">
<% resource.build_customer if resource.customer.nil? %>
<% resource.build_account if resource.accounts.nil? %>
<% resource.build_address if resource.address.nil? %>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<h3>User Info</h3>
<div class="form-group">
<!-- fields for User object -->
<div class="field">
<%= f.label :username %><br />
<%= f.text_field :username, autofocus: true %>
</div>
...
<!-- fields for Customer object -->
<%= f.fields_for :customer do |customer_fields| %>
<div class="field">
<%= customer_fields.label :firstname %>
<%= customer_fields.text_field :firstname %>
</div>
...
<!-- fields for Account object -->
<%= f.fields_for :account do |account_fields| %>
<div class="field">
<%= account_fields.label :acct_type %>
<%= account_fields.text_field :acct_type %>
</div>
<% end %>
<!-- fields for Address object -->
<%= f.fields_for :address do |address_fields| %>
<div class="field">
<%= address_fields.label :address1 %>
<%= address_fields.text_field :address1 %>
</div>
...
The exception is pointing to the block of statements at the top...
<% resource.build_customer if resource.customer.nil? %>
<% resource.build_account if resource.accounts.nil? %>
<% resource.build_address if resource.address.nil? %>
... which has given me trouble before. Before the current error I was getting a similar error from the second line ("build_account"). But that turned out to be a pluralization issue, which I believe I've fixed. Since the HTML is read sequentially, it would seem that there is no problem with the first two build_ methods. Why is there then a problem with the build_address method?
I need to fix this error before I can know if the whole thing will actually work or not. Any ideas?
Thanks
It's Rails 4.1.8 / Devise 3.4.1
The trouble turned out to be the syntax I was using create multiple resource objects. It would pass one, but ignored the rest. What I ended up doing to make it work (or at least make the error go away) was to override the build_resource method to accept an array of parameters for each object to be instantiated:
def new
#user = current_user
build_resource({})
self.resource[:customer => Customer.new, :account => Account.new, :address => Address.new]
respond_with self.resource
end
def build_resource(hash=nil)
hash ||= params[resource_name] || {}
self.resource = resource_class.new(hash)
end
def create
# Override Devise default behavior and create a customer, account, and address as well
resource = build_resource(params[:user])
if(resource.save)
sign_in(resource_name, resource)
respond_with resource, :location => after_sign_up_path_for(resource)
else
render :action => "new"
end
end
Also, I removed the three lines at the top of the form view as they attempted to do some sort of pre-validation in the view and just caused problems. Plenty of validation will happen when the form is submitted. This seems to be doing something good. Now I'm working with the form view and having trouble getting each part to render. Fields_for is rendering fields for User and Account models, but not Customer or Address.

Rails 4.0 with Devise. Nested attributes Unpermited parameters

I am working on a web-app using Devise and Rails 4. I have a User model which I have extended with 2 extra form fields such that when a user signs up he can also submit his first/last names. (based on http://blog.12spokes.com/web-design-development/adding-custom-fields-to-your-devise-user-model-in-rails-4/). I now want to add a Institution model. This model has_many :users, and a user belongs_to :institution. I want to be able to register the institution's name on the same form I register the user. I know I need a nested_attribute in my Institution model, since this is the parent, which I will show in a bit. When I try to sign up the user I get in the console: Unpermited parameters: Institutions.
My hint is that I cannot update my parent class(Institution) based upon my child class (User). Might there be a solution to this? Or has anyone experienced something similar?
class Institutions < ActiveRecord::Base
has_many :users,
accepts_nested_attributes_for :users
end
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
belongs_to :institution
end
registrations/new.html.erb Here I have the nested form
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
.
.
<%= f.fields_for :institutions do |i| %>
<p><%= i.label :name %><br />
<%= i.text_field :institutions_attr %></p>
<% end %>
Based on the tutorial I have linked earlier, I have created a new User::ParameterSanitizer which inherits from the Devise::ParameterSanitizer and overridden the sign_up method as follows:
lib/user_sanitizer.rb
private
def sign_up
default_params.permit(:first_name, :last_name ,:email, :password, :password_confirmation, :current_password, institutions_attributes: [:id, :name])
end
Finally, my application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
protected
def devise_parameter_sanitizer
if resource_class == User
User::ParameterSanitizer.new(User, :user, params)
else
super
end
end
end
Thank you for reading!
Console params output:
{"utf8"=>"✓",
"authenticity_token"=>"JKuN6K5l0iwFsj/25B7GKDj7WEHR4DO3oaVyGxGJKvU=",
"user"=>{"email"=>"abc#foo.com",
"first_name"=>"abc",
"last_name"=>"xyz",
"institutions"=>{"name"=>"Government"},
"password"=>"[FILTERED]",
"password_confirmation"=>"[FILTERED]"},
"commit"=>"Sign up"}
EDIT
As suggested, I have added
params.require(resource_name).permit( :email, :first_name, :last_name, institution: [:name], :password, :password_confirmation ) and I get an *error syntax error, unexpected ',', expecting => ...nstitution: [:name], :password, :password_confirmation )*
BUT, if I re-edit to
params.require(resource_name).permit( :email, :first_name, :last_name, :password, :password_confirmation, institution: [:name] )
I get NO syntax error but I get Unpermited parameters: Institutions in the Request.
My belief is that this happens because User is a child of Institution. I have, however, been unable to find a work-around this.
config/routes.rb
Create your own registration controller like so ... (see Devise documentation for the details of overriding controllers here ...) ... which is more elegant way as opposed to doing it via the ApplicationController
devise_for :users, controllers: {registrations: 'users/registrations'}
app/controllers/users/registrations_controller.rb
Override the new method to create a Profile associated with the User model as below ... run the configure_permitted_parameters method before to sanitize the parameters (note how to add nested parameters)
class Users::RegistrationsController < Devise::RegistrationsController
before_filter :configure_permitted_parameters
# GET /users/sign_up
def new
# Override Devise default behaviour and create a profile as well
build_resource({})
resource.build_profile
respond_with self.resource
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u|
u.permit(:email, :password, :password_confirmation, :profile_attributes => :fullname)
}
end
end
db/migrate/xxxxxxxxxxxxxx_create_profiles.rb
This is the migration that generates the Profile model (note the reference to User) ... this example profile only keeps fullname as an extension of the User but feel free to add as you wish!
class CreateProfiles < ActiveRecord::Migration
def change
create_table :profiles do |t|
t.references :user
t.string :fullname
t.timestamps
end
end
end
app/models/user.rb
class User < ActiveRecord::Base
# Associations
has_one :profile, dependent: :destroy, autosave: true
# Allow saving of attributes on associated records through the parent,
# :autosave option is automatically enabled on every association
accepts_nested_attributes_for :profile
# Devise
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
app/models/profile.rb
class Profile < ActiveRecord::Base
# Associations
belongs_to :user
# Validations
validates :fullname, presence: true
end
app/views/devise/registrations/new.html
<% resource.build_profile if resource.profile.nil? %>
<%= form_for(resource, :as => resource_name,
:url => registration_path(resource_name)) do |f| %>
<ul>
<%= devise_error_messages! %>
<li class="fullname">
<%= f.fields_for :profile do |profile_fields| %>
<%= profile_fields.label :fullname %>
<%= profile_fields.text_field :fullname %>
<% end %>
</li>
<li class="email">
<%= f.label :email %>
<%= f.email_field :email, :autofocus => true %>
</li>
<li class="password">
<%= f.label :password %>
<%= f.password_field :password %>
</li>
<li class="password">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation %>
</li>
<li>
<%= f.submit %>
</li>
<li>
<p><%= render "devise/shared/links" %></p>
</li>
</ul>
<% end %>
You must create your own registration controller to do so, here is how:
routes.rb
devise_for :users, controllers: {registrations: 'registrations'}
Controller
You must replace :your_fields by the fields you want to allow (sorry if I leave that to you, but that makes my answer more general, therefore usable for anyone that would pass by)
class RegistrationsController < Devise::RegistrationsController
private
def sign_up_params
allow = [:email, :your_fields, :password, :password_confirmation]
params.require(resource_name).permit(allow)
end
end
Additional info (nested attributes + some testing)
Also note that if you are using association and accepts_nested_attributes_for you will have params structured like this
model: {field, field, field, associated_model: {field, field}}
And off course you must use the same structure in your sign_up_params method. If you need to understand this, you can change the content of sign_up_params method like this:
def sign_up_params
params.require(resource_name).permit!
end
That will allow any param, then post your form (it should pass this time) and look into your rails console to see the structure of params, finally you can set-up sign_up_params method correctly
Check this for more info http://www.railsexperiments.com/using-strong-parameters-with-nested-forms/
In your case you should use:
params.require(resource_name).permit( :email, :first_name, :last_name, institutions: [:name], :password, :password_confirmation )
Using rails 5.1 and devise 4.4.1 following is the shortest and works pretty good:
app/models/user.rb
after_initialize do
build_profile if new_record? && profile.blank?
end
app/controllers/application_controller.rb
before_action :configure_permitted_parameters, if: :devise_controller?
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [{ profile_attributes: :name }])
end
The key here is that you can do following without making separate controller:
permit nested attributes
build relation for form builder

Rails Devise registration with an additional model

I've searched for about an hour now and found an immense amount of questions describing how to add fields to the Devise user model. However I couldn't find any that explain in a clear way how to add one or multiple models to the registration process.
At registration I want the user to fill out an e-mailaddress, password and in addition my client model, company model and address model (so I have all the information the webapplication needs to run properly).
My models are like this
user.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :remember_me, :client
belongs_to :client
end
client.rb
class Client < ActiveRecord::Base
attr_accessible :bankaccount, :email, :logo, :mobile, :phone, :website
has_many :users
has_one :company
has_one :address
accepts_nested_attributes_for :company, :address
end
I think the only way to do this is to create my own RegistrationsController so I can do #client = Client.new and then do this in my view:
<%= f.simple_fields_for #client do |ff| %>
<%= f.simple_fields_for :company do |fff| %>
<% field_set_tag t(:company) do %>
<%= ff.input :name %>
<% end %>
<% end %>
<%= f.simple_fields_for :address do |fff| %>
//address inputs
<% end %>
<% end %>
<fieldset>
<legend><%= t(:other) %></legend>
// other inputs
</fieldset>
<% end %>
The reason I need it to work this way is because I have multiple users who can represent the same client (and thus need access to the same data). My client owns all the data in the application and therefor needs to be created before the application can be used.
Okay, it took me about 8 hours but I finally figured out how to make it work (if someone has a better/cleaner way of doing this, please let me know).
First I've created my own Devise::RegistrationsController to properly build the resource:
class Users::RegistrationsController < Devise::RegistrationsController
def new
resource = build_resource({})
resource.build_client
resource.client.build_company
resource.client.build_address
respond_with resource
end
end
After that I just needed to adjust config/routes.rb to make it work:
devise_for :users, :controllers => { :registrations => "users/registrations" } do
get '/users/sign_up', :to => 'users/registrations#new'
end
Also I had an error in my devise/registrations/new.html.erb. It should have been f.simple_fields_for :client instead of f.simple_fields_for #client.
Now it properly creates all the objects for the nested attributes and automatically saves it when saving the resource.

Resources