I'm creating a simple upvote/downvote system similar to reddit's, where users can upvote/downvote something and change their minds if need be.
I have a page that makes an AJAX call to the 'create' action of my controller. The controller has no problem creating the record and returning the proper js.erb. However, I'd like to see if an existing post exists, and if so, I'd like to destroy it. My controller looks like this:
def create
#vote = GameVote.new
#vote.game_id = params[:game_id]
#vote.vote = params[:vote]
#vote.user_id = session[:user_id]
existing_vote = GameVote.where(whatever)
respond_to do |format|
if #vote.save
format.js
end
end
end
It just seems to ignore the middle query, preventing me from destroying it if it exists before attempting to save the new entry. Any ideas?
It seems more natural to update the existing GameVote (if one exists) instead of pair delete+create.
To do so just replace:
#vote = GameVote.new
#vote.game_id = params[:game_id]
#vote.vote = params[:vote]
#vote.user_id = session[:user_id]
existing_vote = GameVote.where(whatever)
with:
#vote = GameVote.where(game_id: params[:game_id], user_id: session[:user_id]).first_or_initialize
#vote.vote = params[:vote]
Try :
#vote = GameVote.find_or_create_by_game_id_and_user_id(params[:game_id], session[:user_id])
OR
#vote = GameVote.find_or_create(:game_id => params[:game_id], :user_id => session[:user_id])
#vote.vote = params[:vote]
Related
I have this action in my rails controler,
def step_submit
validate_user()
#owning = #user.create_user_car_transaction(Variant.find(params[:variant]), params[:details], params[:address], params[:somethin1])
Contact.user_contact(current_user, params[:contact]) if #user.contact.nil?
redirect_to "/next_step"
end
I use codeClimate to check the quality of the code..
it shows this action's complexity ~ 30 ..
I actually broke a really huge method into this.. how can i still reduce this complexity?
these are the different methods the action calls
def self.user_contact(user, contact_hash = nil)
contact = user.contact || user.create_contact()
contact.update_attributes(contact_hash) if contact_hash.present?
contact
end
def validate_user
if params[:user] && current_user.nil?
user = User.create(params[:user])
sign_in user
end
end
def create_user_car_transaction(car, details_hash, address_hash, coupon_hash = nil)
transaction = self.transactions.create()
car.transaction_item = transaction.transaction_items.create()
car.save
payment_hash = details_hash
payment_hash.merge!(address_hash)
payment = transaction.create_payment(payment_hash)
transaction.update_attributes(:status=>"1") if transaction.status.nil?
transaction
end
I have a form to create a new Contact model.
I enter the values by hand by cutting and pasting.
Sometimes I end up adding white space on the left and right.
Here is what is in the create controller (I have a loop that checks if I have uploaded a vcard which, obviously, doesn't typically present the problem (although it could) -- but my big problem is when I type it myself.
def create
#contact = Contact.create(params[:contact])
unless #contact.vcard.path.blank?
paperclip_vcard = File.new(#contact.vcard.path)
#vcard = Vpim::Vcard.decode(paperclip_vcard).first
#contact.title = #vcard.title
#contact.email = #vcard.email
#contact.first_name = #vcard.name.given
#contact.last_name = #vcard.name.family
#contact.phone = #vcard.telephone
#contact.address.street1 = #vcard.address.street
#contact.address.city = #vcard.address.locality
#contact.address.state = #vcard.address.region
#contact.address.zip = #vcard.address.postalcode
#contact.company_name = #vcard.org.fetch(0)
end
#contact.user_id = current_user.id # makes sure every new user is assigned an ID
if #contact.save
#check if need to update company with contact info
#contact.update_company
#contact.new_todos #create the todos for the newly created contact
flash[:notice] = "Successfully created contact."
redirect_to #contact
else
render :action => 'new'
end
end
This might help: http://scottmoonen.com/2009/05/08/rails-pattern-trim-spaces-on-input/
I have a after_create method for my Contact model.
However, when I put the value, it comes out nil. How can I have a callback for a newly created model ( I do a fair amount of transformation in the create model) referenced within the callback method?
after_save :update_company
def update_company
puts self.inspect
puts self.company
if company.phone.empty?
company.phone = self.phone
company.save
end
end
When I look at the logs for self.inspect, it doesn't show any of the transformations used in the create method...yet, this should run only after it has created (and saved), the object, right?
Here is the create method:
def create
#contact = Contact.create(params[:contact])
unless #contact.vcard.path.blank?
paperclip_vcard = File.new(#contact.vcard.path)
#vcard = Vpim::Vcard.decode(paperclip_vcard).first
#contact.title = #vcard.title
#contact.email = #vcard.email
#contact.first_name = #vcard.name.given
#contact.last_name = #vcard.name.family
#contact.phone = #vcard.telephone
#contact.address.street1 = #vcard.address.street
#contact.address.city = #vcard.address.locality
#contact.address.state = #vcard.address.region
#contact.address.zip = #vcard.address.postalcode
#contact.company_name = #vcard.org.fetch(0)
end
#contact.user_id = current_user.id # makes sure every new user is assigned an ID
if #contact.save
flash[:notice] = "Successfully created contact."
redirect_to #contact
else
render :action => 'new'
end
end
Yes, this happens because you didn't use self when assigning the value to company object.
In ruby, generally you don't require the use have "self" to retrieve attributes of an instance
for example in your code. you can puts company and it would work fine.
but when assigning (on the left hand side ) you always have to use self.
so change this in your code.
self.company.phone = self.phone
company.save
or
self.company.phone = phone
company.save
I have the following create method for a Contact controller:
def create
puts "in create method"
#contact = Contact.create(params[:contact])
unless #contact.vcard.path.blank?
paperclip_vcard = File.new(#contact.vcard.path)
#vcard = Vpim::Vcard.decode(paperclip_vcard).first
#contact.title = #vcard.title
#contact.email = #vcard.email
#contact.first_name = #vcard.name.given
#contact.last_name = #vcard.name.family
#contact.phone = #vcard.telephone
#contact.address.street1 = #vcard.address.street
#contact.address.city = #vcard.address.locality
#contact.address.state = #vcard.address.region
#contact.address.zip = #vcard.address.postalcode
#contact.company_name = #vcard.org.fetch(0)
end
#contact.user_id = current_user.id # makes sure every new user is assigned an ID
if #contact.save
#check if need to update company with contact info
#contact.update_company
flash[:notice] = "Successfully created contact."
redirect_to #contact
else
render :action => 'new'
end
end
The callback I want to run should be done after the if #contact.save line at the very end of the method...but right now, it runs it in the first .create.
How do I allow a call back to run only after all the processing in the create method is completed?
Basically, ActiveRecord::Callback create(...) - Creates an object (or multiple objects) and saves it to the database, if validations pass. The resulting object is returned whether the object was saved successfully to the database or not.
You need to use (this is going from your script logic) instead:
#contact = Contact.new(params[:contact])
If you want to callback save, use after_save callback.
Could anyone help with this problem:
Upon "create", the user is redirected to the url: model/model_id (eg post/1), instead I am redirected to models/url_encoding_object (eg posts/.%23) and there is an "406 Not Acceptable" message in the console.
Typically, upon create, the console's message is "Processing PostsController#create (for 000.0.0.0 at 2009-11-23 12:32:52) [POST]", but with this error, the message is "Processing PostsController#create to # (for 000.0.0.0 at 2009-11-23 12:32:52) [POST]"
I've seen austinfromboston's response and tried his "old fashioned but effective" solution to that similar problem, but it doesn't work for me.
Any help would be greatly appreciated
Controller Code:
# POST /groups
# POST /groups.xml
def create
#group = Group.new(params[:group])
#group.category = params[:category]
#group.user = current_user
#here we add the current user to the membership collection of the group
#membership = #group.memberships.build(params[:membership])
#membership.group = #group
#membership.user = current_user
#membership.initiator = false
#membership.membership_status_id = 2
#and here we set the current_user as the owner of the group
#group_permission = #group.group_permissions.build(params[:group_permission])
#group_permission.membership = #membership
#group_permission.group_role = GroupRole.find_by_name('Owner')
unless params[:metro_area_id].blank?
#group.metro_area = MetroArea.find(params[:metro_area_id])
#group.state = (#group.metro_area && #group.metro_area.state) ?
#group.metro_area.state : nil
#group.country = #group.metro_area.country if (#group.metro_area &&
#group.metro_area.country)
else
#group.metro_area = #group.state = #group.country = nil
end
#group.tag_list = params[:tag_list] || ''
# unless #user.is_in_group?(#group)
# #user.memberships << #group
# end
respond_to do |format|
if #group.save
flash[:notice] = :group_was_successfully_created.l
format.html { redirect_to(group_path(#group.id)) }
else
format.html {
#metro_areas, #states = setup_metro_area_choices_for(#group)
if params[:metro_area_id]
#metro_area_id = params[:metro_area_id].to_i
#state_id = params[:state_id].to_i
#country_id = params[:country_id].to_i
end
render :action => "new"
}
end
end
end
Looks like either your routes are off somewhere or your model_id parameter is not what you are expecting. Might want to check to see what that parameter is being set to.
It's also really hard to give any suggestions without seeing controller code. Can you post the method making this call?
There's a lot of superfluous code, in your controller. It still works, but you're doing a lot of things the hard way.
Your problem is this line:
format.html { redirect_to(groups_path(#group.id)) }
Which redirects to the collective groups url adding the parameter #group.id.
What it should be is
format.html { redirect_to(group_path(#group.id)) }
# POST /groups
# POST /groups.xml
def create
#group = Group.new(params[:group])
#group.category = params[:category]
#group.user = current_user
#here we add the current user to the membership collection of the group
#membership = #group.memberships.build(params[:membership])
#membership.group = #group
#membership.user = current_user
#membership.initiator = false
#membership.membership_status_id = 2
#and here we set the current_user as the owner of the group
#group_permission = #group.group_permissions.build(params[:group_permission])
#group_permission.membership = #membership
#group_permission.group_role = GroupRole.find_by_name('Owner')
unless params[:metro_area_id].blank?
#group.metro_area = MetroArea.find(params[:metro_area_id])
#group.state = (#group.metro_area && #group.metro_area.state) ? #group.metro_area.state : nil
#group.country = #group.metro_area.country if (#group.metro_area && #group.metro_area.country)
else
#group.metro_area = #group.state = #group.country = nil
end
#group.tag_list = params[:tag_list] || ''
unless #user.is_in_group?(#group)
#user.memberships << #group
end
respond_to do |format|
if #group.save
flash[:notice] = :group_was_successfully_created.l
format.html { redirect_to(groups_path(#group.id)) }
else
format.html {
#metro_areas, #states = setup_metro_area_choices_for(#group)
if params[:metro_area_id]
#metro_area_id = params[:metro_area_id].to_i
#state_id = params[:state_id].to_i
#country_id = params[:country_id].to_i
end
render :action => "new"
}
end
end
end
What is this .1 doing at the end of the line??
flash[:notice] = :group_was_successfully_created.l
I tried to run similar code in my environment and it choked on that.
It should also reference:
group_path(id)
not
groups_path(id)