rails 4 with nested attributes and nested form - ruby-on-rails-4

I am trying to model my first rails 4 project to make the leap from tutorial to the real world.
The app is a horse show signup.
The user (devise) adds an 'entry'.
The entry can consists one or more 'rides'
Each ride can have a single 'horse' and a single 'rider' (nested forms would allow user to select existing horse and rider or create new one via form during new entry create.
I started to do some nested web forms with Cocoon and Formtastic:
https://github.com/nathanvda/cocoon
buy I have problems with saving related data to tables.
When I save my entry the rides table contains correct values for:
test, entry_id, but not horse_id
The entry table has no ride_id value. It only has user_id (I set in controller manually)
My questions are:
I am sure I am missing a few conceptual concepts but do I have my models associations set up correctly?
How do I edit my current forms to save data correctly?
When I debug in the controller I get what looks to be an odd param value:
{"utf8"=>"√", "authenticity_token"=>"xxxxxxxxxxxxxx=", "entry"=>{"show_date"=>"10/26/2014", "rides_attributes"=>{"1407930343404"=>{"test"=>"Intro B", "horses"=>{"name"=>"Plain Horse", "_destroy"=>""}}}}, "commit"=>"Create Entry", "action"=>"create", "controller"=>"entries"}
I thought I would see 'horses_attributes' within the 'rides_attributes' hash but instead I see just 'horses'.
Any clarification including link to examples would be very appeciated.
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :entries
has_many :rides, :through => :entries
has_many :horses, :through => :entries
has_many :riders, :through => :entries
end
class Entry < ActiveRecord::Base
belongs_to :user
has_many :rides, :dependent => :destroy
has_many :horses, :through => :rides
has_many :riders, :through => :rides
accepts_nested_attributes_for :rides, :allow_destroy => true
accepts_nested_attributes_for :horses
accepts_nested_attributes_for :riders
end
class Ride < ActiveRecord::Base
belongs_to :entry
belongs_to :user
has_one :horse #, :dependent => :destroy
has_one :rider
accepts_nested_attributes_for :horse
accepts_nested_attributes_for :rider
end
class Horse < ActiveRecord::Base
belongs_to :ride # :dependent => :destroy
belongs_to :user, :dependent => :destroy
end
class Rider < ActiveRecord::Base
#belongs_to :ride #, :dependent => :destroy
belongs_to :user, :dependent => :destroy
has_many :rides
end
Here is my partial schema:
create_table "entries", force: true do |t|
t.date "show_date"
t.integer "user_id"
t.integer "ride_id"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "entries", ["ride_id"], name: "index_entries_on_ride_id", using: :btree
add_index "entries", ["user_id"], name: "index_entries_on_user_id", using: :btree
create_table "horses", force: true do |t|
t.string "name"
t.string "horse_ncdcta"
t.string "owner_fname"
t.string "owner_lname"
t.date "coggins_date"
t.integer "ride_id"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "user_id"
end
add_index "horses", ["ride_id"], name: "index_horses_on_ride_id", using: :btree
create_table "riders", force: true do |t|
t.string "first_name"
t.string "last_name"
t.string "rider_ncdcta"
t.boolean "senior"
t.boolean "liability_signed"
t.integer "ride_id"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "riders", ["ride_id"], name: "index_riders_on_ride_id", using: :btree
create_table "rides", force: true do |t|
t.string "test"
t.integer "entry_id"
t.integer "rider_id"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "horse_id"
end
add_index "rides", ["entry_id"], name: "index_rides_on_entry_id", using: :btree
add_index "rides", ["rider_id"], name: "index_rides_on_rider_id", using: :btree
create_table "users", force: true do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
t.string "first_name"
t.string "last_name"
t.string "phone"
end
partial entry controller:
def new
#user=current_user
#entry=Entry.new
end
def create
#entry = Entry.new(entry_params)
#entry.user_id=current_user[:id]
respond_to do |format|
if #entry.save
# example of params value
# {"utf8"=>"√", "authenticity_token"=>"xxxxxxxxxxxxxx=", "entry"=>{"show_date"=>"10/26/2014", "rides_attributes"=>{"1407930343404"=>{"test"=>"Intro B", "horses"=>{"name"=>"Plain Horse", "_destroy"=>""}}}}, "commit"=>"Create Entry", "action"=>"create", "controller"=>"entries"}
debugger
format.html { redirect_to #entry, notice: 'Entry was successfully created.' }
format.json { render :show, status: :created, location: #entry }
else
format.html { render :new }
format.json { render json: #entry.errors, status: :unprocessable_entity }
end
end
end
def entry_params
# added ids based on comments below
params.require(:entry).permit(:show_date, rides_attributes: [:id, :test, :_destroy, horses_attributes: [:name, :id]] )
end
views:
_form.html.haml
= semantic_form_for #entry do |f|
= f.inputs do
= f.label :show_date, "Show Date"
= f.input :show_date, :as => :select, :collection => [['08/03/2014', '08/03/2014'], ['09/14/2014', '09/14/2014'], ['10/26/2014', '10/26/2014'], ['11/15/2014', '11/15/2014']]
%h3 Rides
#rides
= f.semantic_fields_for :rides do |ride|
= render 'ride_fields', :f => ride
.links
= link_to_add_association 'add ride', f, :rides
= f.actions do
= f.action :submit
_ride_fields.html.haml
.nested-fields
= f.inputs do
= f.label :test, "Test"
= f.input :test, :as => :select, :collection => [['Intro A', 'Intro A'], ['Intro B', 'Intro B'], ['Intro C', 'Intro C']]
= f.semantic_fields_for :horses do |horse|
= render 'horse_fields', :f => horse
= link_to_add_association 'add horse', f, :horse
_horse_fields.html.haml
.nested-fields
=f.inputs do
= f.input :name
.links
= link_to_add_association 'add horse', f, :horse

Here's what I think is happening, you're nesting horse within Rides instead of Entry. Ride accepts nested attributes for a has_one horse relationship so you're seeing 'horses'. If you submitted horses against the Entry (which has a has_many relationship) you'd see horses_attributes.
In this section of _form.html.haml you assigned ride to f
= render 'ride_fields', :f => ride
And then in your _ride_fields.html.haml you use that f to create a nested form which is being created off the ride variable (Ride has_one horse).
= f.semantic_fields_for :horses do |horse|
= render 'horse_fields', :f => horse
Because your Ride model has accepts_nested_attributes_for :horse you're seeing horses within the Ride. To see horses_attributes you'll want to create horses against the Entry (which accepts the nested attributes for "horses").
I believe you can fix it by changing the render like this (pass in the Entry model form):
= render 'ride_fields', :f => ride, :e => f
And then the horse nested form like this (from f to e):
= e.semantic_fields_for :horses do |horse|
= render 'horse_fields', :f => horse

When using nested attributes the symbol you pass to form_for has to match the association name. You are doing
f.semantic_fields_for :horses
But rides doesn't have a horses assocation, only a horse association. Because of this rails doesn't realise that you're trying to use nested attributes at all, which is why the data is nested under the key "horses" rather than "horses_attributes". You will of course need to change the permitted params to match.
In addition you don't need all the stuff to manage adding extra horse fields for a ride if a ride can in fact only have one horse. If this was a mistake, then leave your forms alone but change the model so that a ride has_many :horses and accepts_nested_attributes_for :horses

I am now saving relationships correctly with below code (with a one caveat). Thanks to previous posters for getting me headed in the right direction!
Also Formtastic doc link: http://rdoc.info/github/justinfrench/formtastic/Formtastic/Inputs/SelectInput
The caveat: I cannot figure out how to select an existing horse with form select if I do not want to add a new horse (_ride_fields.html.haml). Adding new horse works fine.
When I attempt with current commented code I get error:
undefined method ride_id for Ride
I am not sure if this a formtastic problem, model related, or controller. I will post this as a separate question if I do not figure it out.
I realized in my original posting that I should not have foreign keys (eg ride_id) saved to 'entries' table because they are saved to the related tables (rides) in entry_id field.
entries controller (partial):
class EntriesController < ApplicationController
before_filter :set_horses, :except => [:destroy, :index]
def new
#c_user=current_user[:id]
#user=current_user
#entry = current_user.entries.new
#horses = current_user.horses
end
def create
#entry = current_user.entries.new(entry_params)
respond_to do |format|
if #entry.save
format.html { redirect_to #entry, notice: 'Entry was successfully created.' }
format.json { render :show, status: :created, location: #entry }
else
format.html { render :new }
format.json { render json: #entry.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_horses
if current_user.admin?
#horses=Horse.all
else
#horses = current_user.horses
end
end
# Never trust parameters from the scary internet, only allow the white list through.
def entry_params
params.require(:entry).permit(:show_date, rides_attributes: [:id, :test, :_destroy, horse_attributes: [:name, :id]] )
end
end
entry.rb:
class Entry < ActiveRecord::Base
belongs_to :user
has_many :rides, :dependent => :destroy
has_many :horses, :through => :rides, :dependent => :destroy
has_many :riders, :through => :rides, :dependent => :destroy
accepts_nested_attributes_for :rides, :reject_if => lambda { |a| a[:test].blank? }, :allow_destroy => true
accepts_nested_attributes_for :horses, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true
accepts_nested_attributes_for :riders, :allow_destroy => true
validates_presence_of :show_date
end
ride.rb:
class Ride < ActiveRecord::Base
belongs_to :entry, inverse_of: :entry
belongs_to :user, inverse_of: :user
has_one :horse
has_one :rider
accepts_nested_attributes_for :horse
end
horse.rb:
class Horse < ActiveRecord::Base
belongs_to :ride, :dependent => :destroy
belongs_to :user, :dependent => :destroy
end
_form.html.haml
= semantic_form_for #entry do |f|
= f.inputs do
= f.input :show_date, :as => :select, :collection => ['2014/08/03', '2014/09/14', '2014/10/26', '2014/11/15']
%h3 Rides
#rides
= f.semantic_fields_for :rides do |ride|
= render 'ride_fields', :f => ride
.links
= link_to_add_association 'add ride', f, :rides
= f.actions do
= f.action :submit
_ride_fields.html.haml
.nested-fields
= f.inputs do
= f.label :test, "Test"
= f.input :test, :as => :select, :collection => [['Intro A', 'Intro A'], ['Intro B', 'Intro B'], ['Intro C', 'Intro C']]
= if !#horses.empty?
-# both of next 2 lines give error: undefined method ride_id for <Ride:0x00000008cc3370>
-#= f.input :horse, :as => :select, :collection => #horses
-#= f.input :horse, :as => :select, :member_label => :name
= f.semantic_fields_for :horse do |horse|
= render 'horse_fields', :f => horse
.links
= link_to_add_association 'add new horse', f, :horse
_horse_fields.html.haml
.nested-fields
= f.inputs do
= f.input :name

Related

Nested attributes fail in rails 5, but works in rails 4

I have an exercise called "BillApp" basically it's a Bill that have some products, and i should could make bills, calculate IVA, etc.
I have the next schema:
create_table "bill_items", force: :cascade do |t|
t.integer "amount"
t.integer "product_id"
t.integer "bill_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["bill_id"], name: "index_bill_items_on_bill_id"
t.index ["product_id"], name: "index_bill_items_on_product_id"
end
create_table "bills", force: :cascade do |t|
t.string "user_name"
t.string "dni"
t.date "expiration"
t.float "sub_total"
t.float "grand_total"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "products", force: :cascade do |t|
t.string "name"
t.string "description"
t.float "price"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
Bill model:
class Bill < ApplicationRecord
has_many :bill_items
has_many :products, through: :bill_items
accepts_nested_attributes_for :bill_items
end
BillItem model:
class BillItem < ApplicationRecord
belongs_to :product
belongs_to :bill
end
Product model:
class Product < ApplicationRecord
has_many :bill_items
has_many :bills, through: :bill_items
end
The ProductsController is a normal one, generated by scaffold, it doesn't matter.
BillsController:
class BillsController < ApplicationController
before_action :set_bill, only: [:show, :update, :destroy, :edit]
def new
#bill = Bill.new
#bill.bill_items.build
end
def create
#bill = Bill.new(bill_params)
byebug
#bill.save
end
private
def set_bill
#bill = Bill.find(params[:id])
end
def bill_params
params.require(:bill).permit(:user_name, :dni, { bill_items_attributes: [:product_id, :amount, :bill_id] })
end
end
And finally the Bill new view:
<%= form_for(#bill) do |f| %>
<div>
<%= f.label :user_name %>
<%= f.text_field :user_name %>
</div>
<div>
<%= f.label :dni %>
<%= f.text_field :dni %>
</div>
<%= f.fields_for :bill_items do |fp| %>
<div>
<%= fp.label :product %>
<%= fp.collection_select :product_id, Product.all, :id, :name %>
</div>
<div>
<%= fp.label :amount %>
<%= fp.number_field :amount %>
</div>
<% end %>
<%= f.submit %></div>
<% end %>
The problem is very specific, in rails 5 when it try to call #bill.save it fails and in the errors it shows:
#<ActiveModel::Errors:0x007fd9ea61ed58 #base=#<Bill id: nil, user_name: "asd", dni: "asd", expiration: nil, sub_total: nil, grand_total: nil, created_at: nil, updated_at: nil>, #messages={:"bill_items.bill"=>["must exist"]}, #details={"bill_items.bill"=>[{:error=>:blank}]}>
But it works perfectly in Rails 4.2.6.
The entire project folder is here: https://github.com/TheSwash/bill_app
currentrly in the branch feature/bills_controller
Somebody have an idea about what's happening?
the problem it's the bill_items validation
In rails 5 the belongs_to association required by default
http://blog.bigbinary.com/2016/02/15/rails-5-makes-belong-to-association-required-by-default.html

ActiveRecord::UnknownAttributeError in FavoritesController#create

I am getting unknown attribute 'post' for Favorite. This error normally occurs when I am missing a column in a table. The error is stating this portion is where the issue lies: favorite = current_user.favorites.build(post: post). But there shouldn't be another column called post. Do I have another nested set of params I am missing perhaps that is layered under something? Or is my referential integrity incorrect?
Screenshot of error
Favorites_controller.rb file
class FavoritesController < ApplicationController
def create
post = Post.find(params[:post_id])
favorite = current_user.favorites.build(post: post)
if favorite.save
flash[:notice] = "This post is now favorited."
redirect_to [post.topic, post]
else
flash[:error] = "There was an error favoriting you post. Please try again."
redirect_to [post.topic, post]
end
end
end
Favorites schema
create_table "favorites", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.integer "post_id"
end
Post Controller
class Post < ActiveRecord::Base
has_many :comments, dependent: :destroy
has_many :votes
has_one :summary
belongs_to :user #means the post table has the user table's primary k ey in it
belongs_to :topic
has_many :favorites
#has_one :summary
mount_uploader :avatar, AvatarUploader
#default_scope {order('created_at DESC')}
default_scope {order('rank DESC')}
validates :title, length: {minimum: 5}, presence: true
validates :body, length: {minimum: 20}, presence: true
validates :topic, presence: true
validates :user, presence: true
def create_vote
# self == post
user.votes.create(value: 1, post: self)
end
def markdown_title
(render_as_markdown).render(self.title).html_safe
end
def markdown_body
(render_as_markdown).render(self.body).html_safe
end
def up_votes
votes.where(value: 1).count
end
def down_votes
votes.where(value: -1).count
end
def points
votes.pluck(:value).sum
end
def update_rank
age_in_days = (created_at - Time.new(1970,1,1)) / (60 * 60 * 24) #1 day in seconds
new_rank = points + age_in_days
update_attribute(:rank, new_rank)
end
private
def render_as_markdown
renderer = Redcarpet::Render::HTML.new
extensions = {fenced_code_blocks: true}
redcarpet = Redcarpet::Markdown.new(renderer, extensions)
return redcarpet
end
end
Post table schema
create_table "posts", force: :cascade do |t|
t.string "title"
t.text "body"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "user_id"
t.integer "topic_id"
t.string "avatar"
t.float "rank"
end
Favorites route
rake routes | grep -i favorites
post_favorites POST /posts/:post_id/favorites(.:format) favorites#create
post_favorite DELETE /posts/:post_id/favorites/:id(.:format) favorites#destroy
This line
favorite = current_user.favorites.build(post: post)
should be
favorite = current_user.favorites.build(post_id: post.id)
Because you have post_id in your favourites table not post.

How to let user sign up for an account and user id at same time with rails 4 and devise

I am trying to build a multitenant app using rails 4 and devise. The design I am attempting is that an account has one owner(primary user) and has many users. I have an account being added along with the nested form adding the user. I'm not sure if I have issue with the schema I'm attempting to populate or if I am missing a step that would allow me to add an account and user at the same time, with the account record being populated with the owner_id (primary user) and the user being populated with the account_id.
class Account < ActiveRecord::Base
cattr_accessor :current_id
has_many :users
has_one :owner, class_name: 'User'
validates :owner, presence: true
accepts_nested_attributes_for :owner
end
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
belongs_to :account
end
class AccountsController < ApplicationController
def new
#account = Account.new
#account.build_owner
end
def create
#account = Account.new(account_params)
if #account.save
redirect_to root_path, notice: 'Successfully Created Account!'
else
render action: 'new'
end
end
private
def account_params
params.require(:account).permit(:subdomain, owner_attributes: [:email, :password, :password_confirmation])
end
end
Views/Accounts/new.html.erb
<div class="col-md-6 col-md-offset-3 panel panel-default">
<div class="panel-body">
<h2>Create an Account</h2>
<%= form_for #account do |f| %>
<%= f.fields_for :owner do |o| %>
<%= form_group_for o, :email do %>
<%= o.text_field :email, class: 'form-control' %>
<% end %>
<%= form_group_for o, :password do %>
<%= o.password_field :password, class: 'form-control' %>
<% end %>
<%= form_group_for o, :password_confirmation do %>
<%= o.password_field :password_confirmation, class: 'form-control' %>
<% end %>
<% end %>
<%= form_group_for f, :name, opts= {:label => "Company Name"} do %>
<%= f.text_field :name, class: 'form-control' %>
<% end %>
<%= f.submit class: 'btn btn-primary' %>
<% end %>
</div>
</div>
App/Helper/Form_Helper (view call this)
module FormHelper
def errors_for(form, field)
content_tag(:p, form.object.errors[field].try(:first), class: 'help-block')
end
def form_group_for(form, field, opts={}, &block)
if opts.has_key?(:label)
label = opts.fetch(:label)
else
label = field.to_s
end
has_errors = form.object.errors[field].present?
content_tag :div, class: "form-group #{'has-error' if has_errors}" do
concat form.label(label, class: 'control-label')
concat capture(&block)
concat errors_for(form, field)
end
end
end
DB/schema.rb
ActiveRecord::Schema.define(version: 20140629124546) do
create_table "accounts", force: true do |t|
t.string "name"
t.integer "owner_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "clients", force: true do |t|
t.string "name", null: false
t.text "address"
t.integer "account_id"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "clients", ["account_id"], name: "index_clients_on_account_id"
create_table "users", force: true do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "account_id"
end
add_index "users", ["account_id"], name: "index_users_on_account_id"
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
Currently the design creates both the account and user records. The user record is populated with the account_id, but the account_id isn't populated with the owner_id (user_id).
This is likely in your associations, which are currently incomplete and a bit inaccurate.
If a model's attribute holds a foreign key, like the owner_id attribute on your Account model, then it belongs_to that model it is referencing. Think of it like a cattle brand. If you have the ids of other models on you, you belong to those models. You current have a has_one where you need a belongs_to.
You will also need to set up the inverse association, which is currently lacking in your user model.
Assuming you actually will only ever want a user to be associated with one account (as opposed to a user being on more than one account), you could rearrange your associations like this:
#models/account.rb
class Account < ActiveRecord::Base
has_many :users
belongs_to :owner, class_name: 'User'
accepts_nested_attributes_for :owner
end
#models/user.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
belongs_to :account
has_one :owned_account, class_name: 'Account', foreign_key: 'owner_id'
end
Proper association setup will hopefully fix your issue.

Can't add custom Devise field through view

I've been at this for days, and cannot figure out the problem. When I attempt to Sign Up, it appears to work, but when I check the rails console, it shows no username. I'm able to add one from there and it works fine, but using my Sign Up view it never works. Only the fields that were created when I installed Devise work. I've also added First and Last Name, but I only attempted to get Username working, so the code for names is incomplete. If I've left anything important out, let me know. I'd REALLY appreciate the help.
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
protected
def configure_devise_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) do |u|
u.permit(:email, :username, :password, :password_confirmation)
end
end
.
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 :username, :uniqueness => {:case_sensitive => false}
has_many :posts
has_many :offers
has_many :requests
has_one :profile
def name
"#{first_name} #{last_name}"
end
protected
def self.find_for_database_authentication(warden_conditions)
conditions = warden_conditions.dup
login = conditions.delete(:login)
where(conditions).where(["lower(username) = :value", { :value => login.downcase }]).first
end
end
.
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %>
<%= f.email_field :email, autofocus: true %></div>
<div><%= f.label :username %>
<%= f.text_field :username%><div>
<div><%= f.label :first_name %>
<%= f.text_field :first_name %><div>
...
.
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
def show_user
#user = current_user
render 'show'
end
def index
#user = User.all
end
def new
#user = User.new
render profiles_path
end
def create
#user = User.new(user_params)
if #user.save
redirect_to posts_path, notice: 'User successfully added.'
else
render profiles_path
end
end
def edit
end
def update
if #user.update(user_params)
redirect_to posts_path, notice: 'Updated user information successfully.'
else
render action: 'edit'
end
end
private
def set_user
#user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:name, :first_name, :last_name, :email, :username)
end
end
.
class RegistrationsController < Devise::RegistrationsController
def update
new_params = params.require(:user).permit(:email,
:username, :current_password, :password,
:password_confirmation)
change_password = true
if params[:user][:password].blank?
params[:user].delete("password")
params[:user].delete("password_confirmation")
new_params = params.require(:user).permit(:email,
:username)
change_password = false
end
#user = User.find(current_user.id)
is_valid = false
if change_password
is_valid = #user.update_with_password(new_params)
else
#user.update_without_password(new_params)
end
if is_valid
set_flash_message :notice, :updated
sign_in #user, :bypass => true
redirect_to after_update_path_for(#user)
else
render "edit"
end end
end
Schema:
create_table "users", force: true do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
t.string "first_name"
t.string "last_name"
t.string "username"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
Add this to your ApplicationController
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :username
end
end
Source: https://github.com/plataformatec/devise#strong-parameters

use permalink instead of slug in friendly-id

I am new to friendly-id and i have this in my post.rb model
extend FriendlyId
friendly_id :title, use: :slugged
and friendly_id generator migration is
def change
create_table :friendly_id_slugs do |t|
t.string :slug, :null => false
t.integer :sluggable_id, :null => false
t.string :sluggable_type, :limit => 50
t.string :scope
t.datetime :created_at
end
add_index :friendly_id_slugs, :sluggable_id
add_index :friendly_id_slugs, [:slug, :sluggable_type]
add_index :friendly_id_slugs, [:slug, :sluggable_type, :scope], :unique => true
add_index :friendly_id_slugs, :sluggable_type
end
and i added slug attribute with this migration
def change
add_column :posts, :slug, :string
add_index :posts, :slug
Post.find_each(&:save)
end
but I want use permalink instead of slug field like post.permalink
what i really need to change?
I don't like the name slug, either, it sounds like a naked snail.. The :slug_column option should work. If you do not want to use the default "slug" column then you can define it as follows:
friendly_id :title, use: :slugged, slug_column: :permalink
def change
add_column :posts, :permalink, :string
add_index :posts, :permalink
end