Rails 4 LocalJumpError for nested recourse form - ruby-on-rails

I have a nested recourse called "transactions" inside another recourse "budgets".
All I'm trying to accomplish is for my users to be able to edit individual "transactions". However when I go to /1/transactions/1/edit I get a LocalJumpError saying "no block given (yield)".
There might be a very simple solution to this but I haven't been able to find it yet.
routes.rb:
resources :budgets, :path => '/' do
resources :transactions
end
budget.rb:
class Budget < ActiveRecord::Base
belongs_to :user
has_many :transactions
validates :amount, presence: true
validates :title, presence: true
validates :user, presence: true
validates :amount, numericality: true
extend FriendlyId
friendly_id :title, use: :slugged
def should_generate_new_friendly_id?
new_record?
end
end
transaction.rb
class Transaction < ActiveRecord::Base
belongs_to :user
belongs_to :budget
validates :amount, presence: true
validates :user, presence: true
validates :budget, presence: true
validates :date, presence: true
validates :amount, numericality: true
validates :is_positive, :inclusion => {:in => [true, false]}
end
transactions_controller.rb
def edit
#budget = Budget.friendly.find(params[:budget_id])
#transaction = #budget.transaction
end
And in the view transactions/edit.html.erb:
<%= form_for(#transaction) do |f| %>
What am I missing?

Naming a model Transaction conflicts with ActiveRecord::Transactions. You'll need to rename your model.
http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

Related

Using has_many through inside a module

I have a model Evaluation with a has_many with model Tag through evaluation_tags
I need to add this relationship in this Module, but i don't know how can i do this
class Evaluation < ApplicationRecord
belongs_to :user
belongs_to :teacher
belongs_to :school
belongs_to :subject
has_many :evaluation_tags
has_many :tags, through: :evaluation_tags
accepts_nested_attributes_for :evaluation_tags
validates :teacher_id, presence: true
validates :subject_id, presence: true
validates :school_id, presence: true
validates :user_id, presence: true
validates :rating, presence: true
end
module Wizard
module Evaluation
STEPS = %w(step1 step2 step3).freeze
class Base
include ActiveModel::Model
attr_accessor :evaluation
delegate *::Evaluation.attribute_names.map { |attr| [attr, "#{attr}="] }.flatten, to: :evaluation
def initialize(evaluation_attributes)
#evaluation = ::Evaluation.new(evaluation_attributes)
end
end
class Step1 < Base
validates :teacher_id, presence: true
end
class Step2 < Step1
validates :subject_id, presence: true
end
class Step3 < Step2
validates :school, presence: true
validates :user, presence: true
validates :rating, presence: true
end
end
end
When i access the step3 page, this error appears
undefined method `tag_ids' for #
Can anyone help me?
I think you can use ActiveSupport::Concern, like this:
module Wizard
module Evaluation
extend ActiveSupport::Concern
included do
has_many :tags, through: :evaluation_tags
end
end
end
then your class need to include it:
class Evaluation
include Wizard::Evaluation
end

Skip children validations with condition

I have two ActiveRecords Author and Book.
class Author < ActiveRecord::Base
has_many :books
enum author_type: {
musician: 0,
scientist: 1
}
accepts_nested_attributes_for :books
end
class Book < ActiveRecord::Base
belongs_to :author
validates :name, presence: true
validates :score_url, presence: true
end
Now Book validates presence for both name and score_url,
but I want skip validation for score_url when author.author_type is scientist.
I tried this way, but author can not be found during creation.
class Book < ActiveRecord::Base
belongs_to :author
validates :name, presence: true
validates :score_url, presence: true, if: "author.scientist?"
end
What is the best solution here?
You need to provide a Proc to the conditional validation
validates :score_url, presence: true, if: Proc.new { |book| book.author.scientist? }
if your validation gets any more complex, you should extract the logic to a new method.
validates :score_url, presence: true, if: :author_scientist?
private
def author_scientist?
author.present? && author.scientist?
end

How to created new record on has_one for two model on the same time on Rails?

I need to create new record for two models that belong to the same model on one method.
This is my Model
class Promotion < ApplicationRecord
has_one :promotion_thai ,dependent: :destroy
has_one :promotion_eng ,dependent: :destroy
end
class PromotionThai < ApplicationRecord
belongs_to :promotion
mount_uploader :long_banner, PromotionImageUploader
mount_uploader :square_banner, PromotionImageUploader
mount_uploader :details_image, PromotionImageUploader
validates :promotion_id, presence: true
validates :title, presence: true
validates :description, presence: true
#validates :long_banner, presence: true
#validates :square_banner, presence: true
end
class PromotionEng < ApplicationRecord
belongs_to :promotion
mount_uploader :long_banner, PromotionImageUploader
mount_uploader :square_banner, PromotionImageUploader
mount_uploader :details_image, PromotionImageUploader
validates :promotion_id, presence: true
validates :title, presence: true
validates :description, presence: true
validates :long_banner, presence: true
validates :square_banner, presence: true
end
This is my controller method
def create
promotion = Promotion.new
promotion.build_promotion_eng(promotion_eng_params).build_promotion_thai(promotion_thai_params)
if promotion.save
flash[:success] = 'Success Created Promotion'
redirect_to admins_promotions_path
else
errors_message = promotion.errors.full_messages.join(', ')
redirect_to admins_promotion_new_path, :flash => { :error => errors_message }
end
end
Then when i submit the form i always got this error
undefined method `build_promotion_thai' for #<PromotionEng:0x007f9fdbcb0250> Did you mean? build_promotion
On this line
promotion.build_promotion_eng(promotion_eng_params).build_promotion_thai(promotion_thai_params)
How can i fix this kind of problem?
Thanks!
That's because build_promotion_eng(promotion_eng_params) returns an PromotionEng instance.
This should work fine.
promotion.build_promotion_eng(promotion_eng_params)
promotion.build_promotion_thai(promotion_thai_params)

Second Level Model

I have Locations, Order and Event Models.
class Order < ActiveRecord::Base
belongs_to :event
validates :first_name, presence: true
validates :last_name, presence: true
validates :amount, presence: true, :numericality => {:only_integer=>true, :greater_than =>0}
end
class Event < ActiveRecord::Base
belongs_to :location
validates :title, presence: true
validates :price, presence: true, :numericality => {:greater_than =>0}
end
class Location < ActiveRecord::Base
has_many :events, dependent: :destroy
has_many :orders, through: :events
validates :title, presence: true
validates :size, presence: true, :numericality => {:only_integer=>true,:greater_than =>0}
end
I want to check, in the orders create controller, how many seats the location has.
#orders.events returns me the right event.
if I ask for #order.event.location the return is always "#".
Is this a security issue? I also added in the Location model:
has_many: orders, through: events

Rails: How to validate a primary flag on a one to many relationship

Decided to update the information here based upon the feedback I have received to date and what I currently have setup.
I have been trying to work out the best way to solve this issue but so far I am not coming up with an answer. I have two tables: customers and credit_cards. A customer can have many credit_cards and a credit_card belongs to a customer. Also, a customer can have many addresses and an addresses belongs to a customer.
In my creditcard table I have a column that indicates if a particular credit card is primary. The column name is primary. A customer can have many creditcards but only ONE can be primary.
I was hoping that this could be done via validations but so far I am coming up empty. I've done numerous searches but nothing seems to work :(
The following post seems to indicate how this can be done but I couldn't get this to work:
Validation Solution?
My customer.rb model file is as follows. It's not the entire code in there but the relevant parts.
class Customer < ActiveRecord::Base
track_who_does_it :creator_foreign_key => "created_by", :updater_foreign_key => "updated_by"
has_many :addresses, :dependent => :destroy
accepts_nested_attributes_for :addresses, :reject_if => lambda { |a| a['name'].blank? }, :allow_destroy => true
has_many :creditcards, :dependent => :destroy
accepts_nested_attributes_for :creditcards, :reject_if => lambda { |a| a['name'].blank? }, :allow_destroy => true
has_one :primary_creditcard, ->{ where(primary: "1") }, class_name: Creditcard, autosave: true
validates :addresses, presence: true
validates :creditcards, presence: true
validates :primary_creditcard, presence: true
end
My creditcard.rb model file is as follows.
class Creditcard < ActiveRecord::Base
track_who_does_it :creator_foreign_key => "created_by", :updater_foreign_key => "updated_by"
belongs_to :customer
validates :name, presence: true, length: { maximum: 30}
validates :card_type, presence: true
validates :card_number, presence: true
validates :card_exp, presence: true
validates :card_code, presence: true
end
When I create a new customer with an address and a credit card I always get an validation error message that states the following:
Primary creditcard can't be blank
I would appreciate any help on this.
As per the request, adding in the code from the controller that saves the data:
if #customer.update_attributes(customer_params)
flash[:success] = 'Member was successfully updated.'
else
flash[:error] = "Member was not updated, please see errors."
end
The above is in the update part of the customer controller.
Also, for reference, the customer_params is defined as follows:
def customer_params
params.require(:customer).permit(:first_name, :last_name, :sex, :dob, :cell_phone, :work_phone, :home_phone, :other_phone, :email1, :email2, :referred_via_id,
:referred_cust_id, :cust_notes,
addresses_attributes: [:id, :customer_id, :name, :line1, :line2, :line3, :city, :county, :state, :zip, :billing, :delivery, :addr_notes],
creditcards_attributes: [:id, :customer_id, :name, :card_type, :card_number, :card_exp, :card_code, :primary])
end
You could add an additional relation called primary_creditcard and validate it's presence
class Customer < ActiveRecord::Base
has_many :credit_cards
has_one :primary_creditcard, ->{ where(primary: true) }, class_name: CreditCard
validates :primary_creditcard, presence: true
end

Resources