rails redirect after create problem - ruby-on-rails

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)

Related

what is complex in this method

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

Rails Controller is ignoring queries

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]

is there a DRY way to use strip on all :params when creating a new model in Rails?

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/

NoMethodError in ContainerformatsController#create undefined method `yuvstreams' for #<Containerformat:0x450f560>

I am getting this error, I don't know what happened, it's been working fine few days before but it's not working now. This is the code:
#containerformat = Containerformat.new(params[:containerformat])
if #containerformat.containerFmt == 'TS'
#containerformat = Containerformat.new(params[:containerformat])
#transportstream =
#containerformat.transportstreams.build(params[:transportstream])
#transportstream.save
#program = #transportstream.programs.build(params[:program])
#program.save
#user = #containerformat.users.build(params[:user])
#user.save
if params[:videoCodec_id]!= nil
#stream = #program.streams.build(params[:stream])
#stream.videocodec = Videocodec.find(#stream.videoCodec_id)
#stream.save
end
if params[:audioCodec_id]!= nil
#stream = #program.streams.build(params[:stream])
#stream.audiocodec = Audiocodec.find(#stream.audioCodec_id)
#stream.save
end
end
if #containerformat.containerFmt == 'PS'
#programstream =
#containerformat.programstreams.build(params[:programstream])
#subtitle = #programstream.subtitles.build(params[:subtitle])
#subtitle.save
#programstream.save
#stream = #programstream.streams.build(params[:stream])
#user = #containerformat.users.build(params[:user])
#user.save
if params[:videoCodec_id]!= nil
#stream = #programstream.streams.build(params[:stream])
#stream.videocodec = Videocodec.find(#stream.videoCodec_id)
#stream.save
end
if params[:audioCodec_id]!= nil
#stream = #programstream.streams.build(params[:stream])
#stream.audiocodec = Audiocodec.find(#stream.audioCodec_id)
#stream.save
end
end
if #containerformat.containerFmt == 'YUV'
#yuvstream = #containerformat.yuvstreams.build(params[:avistream])
##subtitle = #yuvstream.subtitles.build(params[:subtitle])
##subtitle.save
#yuvstream.save
#stream = #yuvstream.streams.build(params[:stream])
#user = #containerformat.users.build(params[:user])
#user.save
if params[:videoCodec_id]!= nil
##stream = #programstream.streams.build(params[:stream])
##stream.videocodec = Videocodec.find(#stream.videoCodec_id)
##stream.save
end
if params[:audioCodec_id]!= nil
##stream = #programstream.streams.build(params[:stream])
##stream.audiocodec = Audiocodec.find(#stream.audioCodec_id)
##stream.save
end
end
if #containerformat.containerFmt == 'AVI'
#avistream = #containerformat.avistreams.build(params[:avistream])
#avistream.save
#stream = #avistream.streams.build(params[:stream])
#user = #containerformat.users.build(params[:user])
#user.save
if params[:videoCodec_id]!= nil
#stream = #avistream.streams.build(params[:stream])
#stream.videocodec = Videocodec.find(#stream.videoCodec_id)
#stream.save
end
if params[:audioCodec_id]!= nil
#stream = #avistream.streams.build(params[:stream])
#stream.audiocodec = Audiocodec.find(#stream.audioCodec_id)
#stream.save
end
end
I have yuvstreams as table in my database like other tables avisteams, programstreams table.
You need a has_many :yuvstreams in your Containerformat class.
This defines the relationship between containerformats and yuvstreams from the containerformat point of view. You can find more details in the api docs for the has_many method. Basically though, without that you can't refer to yuvstreams from a containerformat.
One additional point on style. Typically rails uses an _ and camel case to make names more readable. So you would have YuvStream and ContainerFormat as your class name and has_many :yuv_streams as your association definition. Rails expects this kind of naming and can sometimes make educated guesses about things if you use it.

Help me refactor this nasty Ruby if/else statement

so I have this big method in my application for newsletter distribution. Method is for updating rayons and I need to assign a user to rayon. I have relation n:n through table colporteur_in_rayons which has attributes since_date and until_date.
I am a junior programmer and I know this code is pretty dummy :)
I appreciate every suggestion.
def update
rayon = Rayon.find(params[:id])
if rayon.update_attributes(params[:rayon])
if params[:user_id] != ""
unless rayon.users.empty?
unless rayon.users.last.id.eql?(params[:user_id])
rayon.colporteur_in_rayons.last.update_attributes(:until_date => Time.now)
Rayon.assign_user(rayon.id,params[:user_id])
flash[:success] = "Rayon #{rayon.name} has been succesuly assigned to #{rayon.actual_user.name}."
return redirect_to rayons_path
end
else
Rayon.assign_user(rayon.id,params[:user_id])
flash[:success] = "Rayon #{rayon.name} has been successfully assigned to #{rayon.actual_user.name}."
return redirect_to rayons_path
end
end
flash[:success] = "Rayon has been successfully updated."
return redirect_to rayons_path
else
flash[:error] = "Rayon has not been updated."
return redirect_to :back
end
end
def update
rayon = Rayon.find(params[:id])
unless rayon.update_attributes(params[:rayon])
flash[:error] = "Rayon not updated."
return redirect_to :back
end
puid = params[:user_id]
empty = rayon.users.empty?
if puid == "" or (not empty and rayon.users.last.id.eql?(puid))
msg = "Rayon updated.",
else
msg = "Rayon #{rayon.name} assigned to #{rayon.actual_user.name}.",
rayon.colporteur_in_rayons.last.update_attributes(
:until_date => Time.now) unless empty
Rayon.assign_user(rayon.id, puid)
end
flash[:success] = msg[msg_i]
return redirect_to rayons_path
end
there was a some double code. So remove that. But also, there is some business code in the controller, which should not be there. So i should refactor the controller code as follows:
def update
rayon = Rayon.find(params[:id])
if rayon.update_attributes(params[:rayon])
if params[:user_id] != ""
rayon.handle_update_user(params[:user_id]
flash[:success] = "Rayon #{rayon.name} has been succesuly assigned to #{rayon.actual_user.name}."
else
flash[:success] = "Rayon has been successfully updated."
end
return redirect_to rayons_path
else
flash[:error] = "Rayon has not been updated."
return redirect_to :back
end
end
The controller method now clearly deals with the actions that need to be taken, and sets a flash method accordingly if needed.
In the Rayon model you write the code what needs to be done when an update is done by a user:
class Rayon
def handle_update_user(user_id)
if (!users.empty? && users.last.id.eql?(params[:user_id]))
# do nothing!
else
colporteur_in_rayons.last.update_attributes(:until_date => Time.now) unless users.empty?
Rayon.assign_user(rayon.id,params[:user_id])
end
end
end
This clearly seperates the concerns. A rayon should know what happens when a user updates it (the name of the function could be improved to what you actually want it to mean, as that is not entirely clear to me).
It could be shorter, but i like to write explicitely that nothing needs to be done if the last user is the same as the current. Otherwise, actions need to be taken. If i understood correctly.
Here's my take at it. I put a bunch of comments inline describing why I changed what I did.
def update
rayon = Rayon.find(params[:id])
if rayon.update_attributes(params[:rayon])
user_id = params[:user_id] # using same value a couple times
# if-else strongly preferred over unless-else...
# so replace `unless foo.empty?` with `if foo.length > 0`
if user_id.length > 0 # then string != ""
# `if A && B` more readable than `unless X || Y` in my opinion
if rayon.users.length > 0 && rayon.users.last.id != user_id
rayon.colporteur_in_rayons.last.update_attributes(:until_date => Time.now)
end
# same line in if-else; pull outside
Rayon.assign_user(rayon.id, user_id)
flash[:success] = "Rayon #{rayon.name} has been successfully assigned to #{rayon.actual_user.name}."
else
flash[:success] = "Rayon has been successfully updated."
end
# all branches in here return this value, pull outside
return redirect_to rayons_path
else
flash[:error] = "Rayon has not been updated."
return redirect_to :back
end
end
The largest issue I noticed with your code is that you had a lot of duplication in your first if-block. All the branches in the true section reached return redirect_to rayons_path, so that got pulled to the end of the block. You had the same flash[:success] = ... twice, so that got pulled out as well.
if-else is much more readable than unless-else, so try to avoid using the latter. I'm not a fan of one unless immediately nested inside another, so I changed that to a compound if-statement.
One of the primary idioms in Rails is DRY (Don't Repeat Yourself), so try to identify spots where you do have repetitive code.
(Also note that I haven't tested this refactoring -- I'm pretty sure that the logic is still the same, but I can't prove it.)
def update
rayon = Rayon.find(params[:id])
unless rayon.update_attributes(params[:rayon])
flash[:error] = "Rayon has not been updated."
return redirect_to :back
end
if params[:user_id].empty?
msg = "Rayon has been successfully updated."
else
if rayon.users.empty?
Rayon.assign_user(rayon.id,params[:user_id])
msg = "Rayon #{rayon.name} has been successfully assigned to #{rayon.actual_user.name}."
elsif not rayon.users.last.id.eql?(params[:user_id])
rayon.colporteur_in_rayons.last.update_attributes(:until_date => Time.now)
Rayon.assign_user(rayon.id,params[:user_id])
msg = "Rayon #{rayon.name} has been succesuly assigned to #{rayon.actual_user.name}."
end
end
flash[:success] = msg
return redirect_to rayons_path
end

Resources