Rails 4 creating relational record - authentication

I am having some issues creating a record from a relational record. This code creates a new user perfectly however it seems that it skips over creating the user's profile all together. It also throws no errors.
any help would be great.
Model
class User < ActiveRecord::Base
has_one :profile
def self.find_for_facebook_oauth(auth)
if user = User.find_by_email(auth.info.email)
user
else
user = User.create( provider: auth.provider,
uid: auth.uid,
email: auth.info.email,
password: Devise.friendly_token[0,20] )
user.build_profile( username: auth.extra.raw_info.username,
first_name: auth.info.first_name,
last_name: auth.info.last_name,
gender: auth.extra.raw_info.gender,
country: auth.extra.raw_info.locale,
image: auth.info.image )
user
end
end
end

Try user.create_profile instead.http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

I forgot that in my Profile class I had a validation for username
model
class Profile < ActiveRecord::Base
# Use friendly_id
extend FriendlyId
friendly_id :username, use: :slugged
belongs_to :users
mount_uploader :image, ProfileImageUploader
validates :username, presence: true, length: {maximum: 16} # <~~
validates :first_name, presence: true, length: {maximum: 255}
validates :last_name, presence: true, length: {maximum: 255}
validates :gender, presence: true, inclusion: %w(male female)
end
My OmniAuth was not giving the username therefore it was rolling back the commit.

Related

Nested `accepts_nested_attributes_for` hitting `undefined method 'with_indifferent_access'`

I'm writing specs for creating a new account. Here's the situation:
Ruby 2.5.0, Rails 5.2.0.rc1
class Account
has_many :accounts_users, inverse_of: :account
has_many :users, through: :accounts_users
has_one :owner, -> { AccountsUser.admins.order(:id) }, class_name: 'AccountsUser'
accepts_nested_attributes_for :owner
end
class AccountsUser
belongs_to :account, inverse_of: :accounts_user
belongs_to :user, autosave: true, inverse_of: :accounts_user
accepts_nested_attributes_for :user
end
class User
has_many :accounts, through: :accounts_users
has_many :accounts_users, autosave: true, dependent: :destroy, inverse_of: :user
accepts_nested_attributes_for :accounts_users, reject_if: :all_blank
end
# AccountsController#account_create_params
params.require(:account).permit(
:plan_id,
:name,
:subdomain,
{
owner_attributes: {
user_attributes: [
:email,
:first_name,
:last_name
]
}
}
)
# rspec account_create_params
let(:valid_account_params) do
{
plan_id: plan.id,
name: 'Name',
subdomain: 'subdomain',
owner_attributes: {
user_attributes: [
email: 'jane#doe.com',
first_name: 'Jane',
last_name: 'Doe'
]
}
}
end
#account = Account.new(account_create_params)
#> NoMethodError: undefined method `with_indifferent_access' for #<Array:0x000056472e0799c0>
from /usr/local/bundle/gems/activerecord-5.2.0.rc1/lib/active_record/nested_attributes.rb:412:in `assign_nested_attributes_for_one_to_one_association'
It has to be complaining about the user_attributes array, and seeing as it's coming from a method called assign_nested_attributes_for_one_to_one_association, Rails seems to be erroneously thinking that the relationship between AccountsUsers and Users is one to one and not one to many.
I've triple checked the associations. What do you guys think? Rails 5.2 bug perhaps?
There were several issues here. I found that permitting parameters and providing them needed different syntax:
def account_create_params
params.require(:account).permit(
:plan_id,
:name,
:subdomain,
{
owner_attributes: {
user_attributes: [
:email,
:first_name,
:last_name,
:password
]
}
}
)
end
vs
let(:valid_account_params) do
{
plan_id: plan.id,
name: 'Name',
subdomain: 'subdomain',
owner_attributes: {
user_attributes: {
email: email_valid,
first_name: 'Jane',
last_name: 'Doe',
password: 'password'
}
}
}
end
A bit confusing there but it works. The inverse_of on AccountsUser was wrong. I needed plural:
belongs_to :account, inverse_of: :accounts_users, optional: true
belongs_to :user, autosave: true, inverse_of: :accounts_users
And I also needed optional: true on the account belongs to, despite accepts_nested_attributes_for setting up the relationship properly. There was a chicken vs egg situation where the AccountsUser was invalid because the Account didn't exist, and the Account couldn't be saved because the AccountsUser was invalid. This may be a Rails 5 'feature'.

with_options not working in RoR3 model

Can someone please explain to me why it seems to ignore the with_options block in this code?
class User < ActiveRecord::Base
attr_accessible :name,:user_type,:policy_num,:address,:city,:state,:zip,:phone,:fax,:email,
:password, :password_confirmation
has_secure_password
has_many :policies
has_many :dealer_forms
before_save {|user| user.email = email.downcase}
before_save :create_remember_token
ZIP_REGEX = /^\d{5}(-\d{4})?$/
EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
COMPLEX_PHONE_REGEX = /^(?:(?:\+?1\s*(?:[.-]\s*)?)?(?:\(\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\s*\)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\s*(?:[.-]\s*)?)?([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.-]\s*)?([0-9]{4})(?:\s*(?:#|x\.?|ext\.?|extension)\s*(\d+))?$/
validates :name, presence: true, length:{in:4..50}
validates :email, presence: true, uniqueness: {case_sensitive: false},format:{with:EMAIL_REGEX}
validates :password, length:{in:6..20}, if: :password
validates :password_confirmation, presence:true, if: :password
validates :user_type, presence: true, inclusion: {in: %w(Dealer Producer System)}
# Validate True User items skip admin users #
with_options :unless => :is_system_user? do |u|
u.validates :policy_num, presence: true
u.validates :address, presence: true
u.validates :city, presence: true
u.validates :state, presence: true, length:{is: 2}
u.validates :zip, presence: true, format:{with:ZIP_REGEX,message: "Not a valid Zip Code"}
u.validates :phone, allow_blank: true, format:{with:COMPLEX_PHONE_REGEX}
u.validates :fax, allow_blank: true, format:{with:COMPLEX_PHONE_REGEX}
end
private
def create_remember_token
self.remember_token = SecureRandom.urlsafe_base64
end
def is_system_user?
user_type == "System" ? true : false
end
end
I have tried the following:
with_options unless: :is_system_user?
with_options unless: Proc.new{|user| user.user_type == "System"}
with_options unless:"user_type = 'System'"
with_options if: "user_type != 'System'"
but for some reason when I try and create a user in the console it still runs the validations inside the block.
Any help would be greatly appreciated. Thanks

Undefined method 'build' in rails 3

I am getting a "NoMethodError in ProjectsController#create" with the following code:
def create
#project = current_user.project.build(params[:project])
if #project.save
flash[:success] = "Project created!"
redirect_to root_url
end
end
I have tried using #project = current_user.project.create(params[:project]) as well, but I get the same error, albeit for .create.
My Project model looks like this:
class Project < ActiveRecord::Base
attr_accessible :title,
:sub_title,
:desc,
:category
validates :user_id, presence: true
validates :title, presence: true, length: { maximum: 35 }
validates :category, presence: true
belongs_to :user
...
end
and my User model looks like this:
class User < ActiveRecord::Base
attr_accessible :name,
:surname,
:email,
:email_confirmation,
:password,
:password_confirmation
has_secure_password
has_one :project
...
end
From what I can tell, this should create a new Project with an association to the user.id and project.user_id. Any ideas why I get the error instead of successful creation?
For has_one associations you want:
#project = current_user.build_project(params[:project])
The same pattern is used for create:
#project = current_user.create_project(params[:project])
If you look at the has_one documentation they list the methods that get created when you declare the association.

Rails 3.2 + Rolify: Application breaks after installing Rolify (Bug?)

I have this Rails 3.2 application running fine. I installed Rolify by following the steps below:
Add gem "rolify" to the Gemfile
Run bundle install
Run rails g rolify:role
Check the new migrations, the new files and the modified files (generated/modified by the command above).
Run rake db:migrate
At this point, I try to create/edit a User and I get the following error:
NoMethodError in UsersController#create
undefined method `user_id' for #<User:0x007f8f21f168e8>
Note that before I installed Rolify, everything was working fine, so the problem comes from Rolify.
Here are the migration, the new file and the modified file in question:
The new migration:
class RolifyCreateRoles < ActiveRecord::Migration
def change
create_table(:roles) do |t|
t.string :name
t.references :resource, :polymorphic => true
t.timestamps
end
create_table(:users_roles, :id => false) do |t|
t.references :user
t.references :role
end
add_index(:roles, :name)
add_index(:roles, [ :name, :resource_type, :resource_id ])
add_index(:users_roles, [ :user_id, :role_id ])
end
end
The new model:
class Role < ActiveRecord::Base
has_and_belongs_to_many :users, :join_table => :users_roles
belongs_to :resource, :polymorphic => true
end
The modified model:
class User < ActiveRecord::Base
rolify
has_secure_password
has_many :issues
acts_as_tenant(:client)
attr_accessible :email, :password, :password_confirmation, :username
validates :username, presence: true,
length: { within: 4..50 },
format: { with: /(?:[\w\d]){4,255}/ }
validates_uniqueness_to_tenant :username, case_sensitive: false
validates :email, presence: true,
uniqueness: { case_sensitive: false },
length: { within: 8..255 },
format: { with: /^[-a-z0-9_+\.]+\#([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i }
validates :password, presence: true, on: :create,
confirmation: true,
length: { within: 4..255 }
validates :password_confirmation, presence: true, on: :create
# NOTE: Used by SimpleForm to display the dropdown proerply
def to_label
"#{username}"
end
end
You can find the rest of the files in the project in the Github repo
Does anyone have a clue where the error comes from please?
This error is happening because the acts_as_tenant is (mistakenly) creating a validation for a user_id field on your User model. You can see this validator if you run this code inside rails c:
User._validators
I would recommend to switch to the apartment gem which appears to be more maintained than acts_as_tenant.

Rails 3 - trying to create polymorphic has_one association in console

Here's my code:
Models:
class Article < ActiveRecord::Base
attr_accessible :title, :author, :content, :imageable_attributes
has_one :image, as: :imageable, dependent: :destroy
accepts_nested_attributes_for :image, allow_destroy: true
validates_presence_of :title, :content, :author
end
class Image < ActiveRecord::Base
mount_uploader :image, ImageUploader
attr_accessible :image, :caption, :imageable_id, :imageable_type, :article_ref
validates_presence_of :image
belongs_to :imageable, :polymorphic => true
end
Here's what I've tried in console:
article = Article.create!(title: "test", content: "test", author: "test", image_attributes: {image: "test.jpg", caption: "test caption"})
This creates an Article without errors, but if I call:
article.image
I get:
=> nil
If I type in console:
article = Article.new(title: "test", content: "test", author: "test")
article.build_image(image: "test.jpg")
I get:
=> Validation failed: Image image can't be blank
Any help greatly appreciated, I'm very confused!
I believe it's necessary to supply the attachment itself, rather than just the path. As an example,
i = Image.new(
:image => File.join(Rails.root, "test.jpg")
)
i.image
# =>
but
i = Image.new(
:image => File.open(File.join(Rails.root, "test.jpg"))
)
i.image
# => /uploads/tmp/20120427-2155-1316-5181/test.jpg
It's not necessary to use File.open when saving using Multipart POST, though.