Basic Rails 3 saving parent object with association object - ruby-on-rails-3

I have a basic rails question where I need to save two associated objects.
The association is Rtake has_many :companies and Company belongs_to :rtake
def create
#rtake = RTake.new(:email => params[:contact_email])
#rtake.role = "PROVIDER"
#company = #rtake.companies.build(params[:company])
#company.rtake = #rtake
respond_to do |format|
if #company.save_company_and_rtake
format.html{ redirect_to admin_companies_url}
else
flash.now[:errors] = #company.errors.full_messages.join(", ")
format.html{ render "new" }
end
end
end
In my company.rb class I have
def save_company_and_rtake
status1 = self.save(:validate => false)
status2 = self.rtake.save(:validate => false)
status = status1 && status2
status
end
The problem I face is that the company.rtake_id remains nil. Ideally shouldn't the company.rtake_id get updated to the #rtake.id after save.
I know I am missing something basic. Would appreciate some help.

You shouldn't need this line:
#company.rtake = #invitation
#invitation is nil from what you've shown .
But also, when you built the #company, #rtake.id isn't set because it hasn't been saved.

#company = #rtake.companies.build(params[:company])
#company.rtake = #rtake
#rtake.companies.build(params[:company]) This already means #company.rtake == #rtake. it's redundent here.

Related

Ruby on Rails, what's the correct way to relate two instances?

I'm new to learning Rails 3 and working through a Q&A app tutorial. I'm just wondering why I can't do this (I get an error) in relating a particular answer to a question. It works for the current user...
class AnswersController < ApplicationController
before_filter :auth, only: [:create]
def create
#question = Question.find(params[:question_id])
**#answer = Answer.new(params[:answer])
#answer.question = #question
#answer.user = current_user**
if #answer.save
flash[:success] = 'Your answer has been posted!'
redirect_to #question
else
#question = Question.find(params[:question_id])
render 'questions/show'
end
end
end
The tutorial says that this is the correct way:
class AnswersController < ApplicationController
before_filter :auth, only: [:create]
def create
#question = Question.find(params[:question_id])
**#answer = #question.answers.build(params[:answer])**
#answer.user = current_user
if #answer.save
flash[:success] = 'Your answer has been posted!'
redirect_to #question
else
#question = Question.find(params[:question_id])
render 'questions/show'
end
end
end
Doing the following
#answer = #question.answers.build(params[:answer)
Is the same as doing this
#answer = Answer.new(params[:answer])
#answer.question_id = #question.id
Doing a build adds the relation attributes to the new answer, in this case question_id
As for the error, can you provide the type of error you receive?

Rails render mail_form gem from a different controller

From travels, which belongs to offer, I'm trying to render a form generated with the mail_form gem.
But I get an error with this message:
*undefined method `model_name' for NilClass:Class*
travels/show
= render :partial => '/question_forms/form', :question_form => #question_form
Any hint how to get this? I've tried including the question_form model as an association to travel, but it doesn't work.
This is the question_forms_controller default code:
class QuestionFormsController < ApplicationController
def new
#question_form = QuestionForm.new
end
def create
begin
#question_form = QuestionForm.new(params[:question_form])
#question_form.request = request
if #question_form.deliver
flash.now[:notice] = 'Thank you for your message!'
else
render :new
end
rescue ScriptError
flash[:error] = 'Sorry, this message appears to be spam and was not delivered.'
end
end
end
In my travels_controller I tried to load #question_form using the same method, but this doesn't seem the way:
def new
#offer_season = OfferSeason.find(params[:offer_season_id])
#travel = #offer_season.travels.find(params[:id])
#question_form = #travel.questionforms.new
end
def create
#offer_season = OfferSeason.find(params[:offer_season_id])
#travel = #offer_season.travels.find(params[:id])
begin
#question_form = #travel.questionforms.new(params[:question_form])
#question_form.request = request
if #question_form.deliver
flash.now[:notice] = 'Thank you for your message!'
else
render :new
end
rescue ScriptError
flash[:error] = 'Sorry, this message appears to be spam and was not delivered.'
end
end

how can i use Capybara without tests

in my Rails app in DB i have some query.
# PostController
#post.query # => 'blabla'
and i want put this string in google or yahoo
in simple ruby file i use
require ... all gems
Capybara.app_host = 'http://www.google.com/'
and
class Google
include Capybara::DSL
def search
visit('/')
fill_in "q", :with => "blah blah"
click_button("Google")
...
but how can I put this code in controller (or model method)?
Capybara is not intended for such use. You might want to try mechanize instead.
class PostsController < ApplicationController
require 'capybara'
require 'capybara/dsl'
include Capybara::DSL
Capybara.current_driver = :webkit
def index
#posts = Post.all
end
def show
#post = Post.find(params[:id])
visit(#post.search_type)
fill_in "q", :with => #post.query
click_button("Google")
loop_variable = 0
num_of_page = 1
max_count_of_page = 4
flag_on_break = false
while(loop_variable == 0) do
has_on_page = page.has_content?(#post.search_question)
if has_on_page
loop_variable = 1
else
find('.b:last a').click
num_of_page += 1
end
if num_of_page > max_count_of_page
flag_on_break = true
break
end
end
if flag_on_break
#number = 'Nothing not found'
else
#number = num_of_page
end
end
def new
#post = Post.new
end
def create
#post = Post.new(params[:post])
if #post.save
flash[:notice] = "Post created!"
redirect_to root_path
end
end
end
this is a piece of my code - but the main idea, I think, is understandable

Populating form after validation fails

I have report_controller where I have two objects, #report and #reporte, and I want to save both objects in database. When validation fails, I want to get fields populated in rendered form.
I can't use just #report = ReportMain.new(params[:report_main]) because I have two objects and just one params object.
I use exportnew action to show form, and encreate to save this form.
There is some simple way to get form populated?
ReportController:
class ReportController < ApplicationController
before_filter :authenticate_user!
before_filter :load
layout "application"
def load
#company = Company.find_by_id(current_user.company_id)
#date = Date.today
#report = ReportMain.new
#reporte = ReportE.new
end
def index
list
render("list")
end
def list
#reports = ReportMain.all
end
def exportnew
render("ennew")
end
def encreate
#report = ReportMain.new
#reporte = ReportE.new
#reportparam = params[:report_main]
#report.waste_id = params[:waste][:code]
#report.warehouse_id = Warehouse.find_by_user_id(current_user.id).id
#report.user_id = current_user.id
#report.company_id = current_user.company_id
#report.amount = #reportparam[:amount]
#report.isimport = false
#report.isfinished = false
#report.reportnumber = ReportMain.where(:company_id => current_user.company_id).count.to_i+1
if #report.save
#reporte.report_main_id = #report.id
else
#report_main = #report
render("etnew")
return
end
#reporte.vrstaotpada = params[:vrstaotpada]
#reporte.nacinpakovanja = params[:nacinpakovanja]
#reporte.ispitivanjebroj = #reportparam[:ispitivanjebroj]
#reporte.datumispitivanja = #reportparam[:datumispitivanja]
#reporte.q_pripadnost = #reportparam[:q_pripadnost]
#reporte.datumpredaje = #date
if #reporte.save
redirect_to(:action => 'show', :id => #reporte.id)
flash[:notice] = "Izveštaj je uspešno kreiran."
else
#report_main = #report
render("etnew")
end
end
def show
#report = ReportMain.find(params[:id])
#warehouse = #report.warehouse.name
end
end
View starts with (it's huge HTML):
<%= form_for(:report_main, :url => {:action => 'encreate'}) do |f| %>
Since you want your form to get populated after validation fails, I suggest make your from to submit through AJAX. There is a jQuery plugin which can help http://jquery.malsup.com/form/

Ensuring that at least one related record still exists

Is there a better way to ensure that I don't delete the last record of a relation? I feel like this should be done through a validation, but could not make that stop the destroy action.
FYI - #organization is present because nested routes
class LocationsController < ApplicationController
....
....
def destroy
#organization = Organization.find(params[:organization_id])
#location = #organization.locations.find(params[:id])
count = Location.find_all_by_organization_id(#location.organization_id).count
if count > 1
#location.destroy
flash[:notice] = "Successfully destroyed location."
redirect_to #organization
else
flash[:notice] = "Could not destroy the only location."
redirect_to #organization
end
end
end
You might also consider the before_destroy callback (though I don't think your version is all that bad):
http://edgeguides.rubyonrails.org/active_record_validations_callbacks.html#destroying-an-object