going to new page sets my user_id to null in Rails - ruby-on-rails

I have 2 models .. one for User(amitian) and other about
They have a has_one and belongs_to association
Problem is that whenever I create a new about it works fine and set my amitian_id to current_amitian but whenever I go to my new page again.. it updates my amitian_id to NULL
for eg.
this is my sql after I submit the form
insert into about_amitian('values' , amitian_id = 1)
and if i go to new page again it says
update about_amitian set amitian_id = null where about_amitian.id= 1
this is my controller and model
class AboutAmitiansController < ApplicationController
before_action :authenticate_amitian!
def new
#amitian = current_amitian
#about_amitian = #amitian.build_about_amitian
end
def create
#amitian = current_amitian
#about_amitian = #amitian.create_about_amitian(about_amitian_params)
if #about_amitian.save
redirect_to root_url
flash[:notice] = 'success'
else
render root_url
end
end
private
def about_amitian_params
params.require(:about_amitian).permit(:dob,:interest,:bio,:catch_phrase,:relationship_status)
end
end
and model
belongs_to :amitian
and in amitian
has_one :about_amitian
Why is it Updating my database ?

Related

Rails how to associate 2 models on create?

I would like to associate Order object wit Dispute Object on create of Dispute but when i go create the object in the log shows:
ActiveRecord::RecordNotFound (Couldn't find Order without an ID)
should i not try to find the order in the method?
Someone know how to associate the objects in the creation?
the Dispute Controller is:
class DisputesController < ApplicationController
def new
if current_user.address.blank?
redirect_to edit_user_path
flash[:error] = 'fill the address'
else
#dispute = Dispute.new
end
end
def create
#order = Order.find(params[:id])
if current_user == #order.buyer
dispute = #order.dispute.nil? ? Dispute.new : #order.dispute
dispute.attributes = params[:dispute]
dispute.user = #order.buyer
dispute.buyer_name = #order.buyer_name
dispute.seller_name = #order.seller_name
if dispute.save
flash[:success] = 'Dispute Created'
end
end
The order model
class Order < ActiveRecord::Base
has_one :dispute
end
the dispute model
class Dispute < ActiveRecord::Base
belongs_to :order
end
Without adding parameters or a nested route the request won't know what order is being referenced. You can use nested routes like orders/:order_id/dispute (http://guides.rubyonrails.org/routing.html#nested-resources) and then you can use #order.build_dispute (http://guides.rubyonrails.org/association_basics.html#methods-added-by-belongs-to)
My first thought based on the error you are getting is to check what params you have available upon the form's submission, because it seems it is not finding an Order based on the param you're passing into the find call.
Also check out strong params for security: http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html

redirect_to next instance on update

I'm trying to redirect users to the next instance of my WordExposition model after update. What I have currently works for immediately-adjacent word_exposition id's, but raises RecordNotFound if the next lesson's word_exposition's ID skips (i.e. it will redirect properly between id's 1-4, but will break if the next id is 6). How can I get it to redirect also for those non-adjacent WordExposition instances that belong to the same lesson?
I based the next_exposition model method on the ideas from this post, but I'm missing something to get it to work here.
WordExposition model:
class WordExposition < ActiveRecord::Base
belongs_to :enrollment
belongs_to :word
def next_exposition
WordExposition.where(["id > ? AND enrollment_id = ?", id, enrollment_id]).first
end
end
WordExpositions controller:
class WordExpositionsController < ApplicationController
def update
current_word_exposition
#current_word_exposition.completed = true
#current_word_exposition.term_given_by_student = params[:word_exposition][:term_given_by_student]
if #current_word_exposition.save
flash[:notice] = "Congratulations!"
#currently only redirects correctly for adjacent words in the same lesson, should do so for non-adjacent word_expositions in the same lesson
if next_word = #current_word_exposition.next_exposition
redirect_to lesson_word_exposition_path(current_lesson, next_word)
end
else
flash[:alert] = "Enter the word exactly as shown!"
redirect_to lesson_word_exposition_path(current_lesson, current_word_exposition)
end
end
private
helper_method :current_lesson
def current_lesson
#current_lesson ||= Lesson.find(params[:lesson_id])
end
helper_method :current_enrollment
def current_enrollment
#current_enrollment ||= Enrollment.find_by!(lesson_id: params[:lesson_id], user_id: current_user.id)
end
def word_exposition_params
params.require(:word_exposition).permit(:completed)
end
helper_method :current_word_exposition
def current_word_exposition
#current_word_exposition ||= current_enrollment.word_expositions.find_by!(word_id: params[:id])
end
end
You can try this
def next_exposition
WordExposition.where('id = (select min(id) from word_expositions where id > ?)', self.id).first
end

Rails: first_or_create not saving

My goal for my application is to only show a form page with existing data or a blank form if new. I've accomplished this by using a callback that created a blank record when the user is created.
User model:
before_create :build_health_profile
However, if for whatever reason a users "health_profile" were to be destroyed or non-existant, it breaks my entire app with:
"undefined method `health_profile' for nil:NilClass"
It was mentioned to me that the "first_or_create" method could solve this by show a new form or finding the existing one, but I can't get it to save the fields. It directs to my root with my save alert like it saved, but nothing gets actually saved.
Controller:
class HealthProfilesController < ApplicationController
def new
#health_profile = current_user.build_health_profile
end
def create
#health_profile = HealthProfile.where(user_id: current_user).first_or_create(health_profile_params)
if #health_profile.save
flash[:success] = "Health profile saved."
redirect_to root_path
else
render 'new'
end
end
private
def health_profile_params
params.require(:health_profile).permit(
:age,
:weight,
:height,
:gender
)
end
end
I've seen where I could use a block for "first_or_create", but no luck getting that to work.
View:
<%= link_to "Health Profile", new_health_profile_path %>
Models:
class User < ActiveRecord::Base
has_one :health_profile, dependent: :destroy
end
class HealthProfile < ActiveRecord::Base
belongs_to :user
end
If you use first_or_create then that calls the save method as part of it on the record and tries to save that in the database. If it can't save the record, then the transaction is rolled back. So, you want to use: first_or_initialize here which is like new and does not save the record in the database immediately. It just loads the data. So, you can call save on it in the next line of your code.
So, in your code, where you have:
#health_profile = HealthProfile.where(user_id: current_user).first_or_create(health_profile_params)
Here you are not controlling the save part, that's already being done by the first_or_create method.
So, you actually want to just load the object (NOT save yet) by using first_or_initialize:
#health_profile = HealthProfile.where(user_id: current_user).first_or_initialize(health_profile_params)
and then, in the next line, you can call the save and based on it's return value you can take the decision:
if #health_profile.save
# do stuff if successfully saved health_profile
else
# otherwise
render 'new'
end
Because you have #health_profile.save,
You should change first_or_create into first_or_initialize
first_or_create immediately trigger save, whereas first_or_initialize would just assign the values to a New record or to an already existing record if record exists already
I was able to fix the problem of the record resetting itself when going back to the form by adjusting the new action. Thats everyone for the help.
def new
#health_profile = current_user.health_profile || HealthProfile.new
end
def create
#health_profile = HealthProfile.where(user_id: current_user).first_or_initialize(health_profile_params)
if #health_profile.save
flash[:success] = "Health profile saved."
redirect_to root_path
else
render 'new'
end
end

before_filter to set primary key before create

I am using filter to set the primary key of an instance before saving it.
Here is my controller method:
class ReferencesController < ApplicationController
before_filter :set_primary_key, :only => [:create_sub_reference]
def create_sub_reference
#reference = Reference.new(params[:reference])
respond_to do |format|
if #reference.save
format.js
else
flash[:notice] = "Reference failed to save."
end
end
end
private
def set_primary_key
result = ActiveRecord::Base.connection.execute('SELECT REF_ID FROM SEQUENCES')
inc_result = (result.fetch_row.first)
self.REF_ID = inc_result
end
end
end
I am getting the following error message in the log file when i click on the 'Save button':
NoMethodError (undefined method `REF_ID=' for #<ReferencesController:0xb69f4ca8>):
Thanks for any suggestion on this matter
You're trying to set the REF_ID attribute - which I assume is a database column - on your Controller, not your model. That code will be invoked every time a web request for ReferencesController reaches your app.
Perhaps you wanted to move the logic to a before_create hook in the References model?

Rails 3. Why is my nested record deleted when I go to the Edit page?

Every company is supposed to have one CompanyContact. My Company form has fields for company contacts. When I update the Company and add a new company contact, it works fine, because in the show page for company, it does show the new company contact. But when I click the Edit link that takes me to the Edit page (note: I don't even click the update button yet), in the Edit Company form where the companycontact is supposed to be is blank. So i check the logs and the companycontact was deleted.
DELETE FROM "company_contacts" WHERE "company_contacts"."id" = ? [["id", 4]]
I'm confused because I haven't called any delete action.
----------------------------------------
company.rb
has_one :company_contact, :dependent => :destroy
accepts_nested_attributes_for :company_contact
----------------------------------------
company_contact.rb
belongs_to :company
----------------------------------------
companies_controller.rb
def new
#company = Company.new
company_contact = #company.build_company_contact
respond_to do |format|
format.html # new.html.erb
format.json { render json: #company }
end
end
def edit
#company = Company.find(params[:id])
company_contact = #company.build_company_contact
end
In your edit action you're building a company contact for your company, but your company has only one company contact. Check for existence before building a new one:
company_contact = #company.company_contact || #company.build_company_contact
I found this in the ActiveRecord source, which confirms the suspicion I commented on above (comments in the code below are mine):
class HasOneAssociation < SingularAssociation #:nodoc:
def replace(record, save = true)
raise_on_type_mismatch(record) if record
load_target
reflection.klass.transaction do
# !!!
# This is where your record is getting deleted
# !!!
if target && target != record
remove_target!(options[:dependent]) unless target.destroyed?
end
if record
set_owner_attributes(record)
set_inverse_instance(record)
if owner.persisted? && save && !record.save
nullify_owner_attributes(record)
set_owner_attributes(target) if target
raise RecordNotSaved, "Failed to save the new associated #{reflection.name}."
end
end
end
self.target = record
end
...
This replace method appears to be called whenever record.build_association is used.
Your edit action shouldn't build the associated record if one already exists.

Resources