Belongs_to relationship in edit - ruby-on-rails

I'm encountering a problem when editing a form with a belongs_to relationship (extra_guest belongs_to age_table).
I am able to create a new extra_guest and assign it to an age_table, but I cannot get the edit/update to work as my update function returns a falseClass.--> #extra_guest.update(extra_guest_params).errors.full_messages returns undefined method `errors' for false:FalseClass
Code
models
class ExtraGuest < ApplicationRecord
belongs_to :age_table
validates :age_table, presence: true
end
class AgeTable < ApplicationRecord
belongs_to :park
has_many :extra_guests, dependent: :destroy
validates :name, :age_from, :age_to, presence: true
validates_associated :extra_guests
end
class Attraction < ApplicationRecord
belongs_to :park
has_many :extra_guests, dependent: :destroy
accepts_nested_attributes_for :extra_guests, allow_destroy: true
validates :name, presence: true
end
class Park < ApplicationRecord
has_many :attractions, dependent: :destroy
has_many :age_tables, dependent: :destroy
validates :name, :currency, presence: true
end
extra_guests_controller
def edit
#extra_guest = ExtraGuest.find(params[:id])
#age_table = #extra_guest.age_table
#age_table_list = AgeTable.where(park: #attraction.park)
end
def update
#extra_guest = #attraction.extra_guests.find(params[:id])
#age_table = AgeTable.find(params[:age_table])
authorize #extra_guest
if #extra_guest = #extra_guest.update(extra_guest_params)
redirect_to root_path
else
#attraction = Attraction.find(params[:attraction_id])
#extra_guest = ExtraGuest.find(params[:id])
#age_table_list = #attraction.park.age_tables
render 'edit'
end
end
private
def extra_guest_params
params.require(:extra_guest).permit(:name, :age_table_id,
extra_guest_prices_attributes: [:id, :name, :price_type, :start_date, :end_date, :price, :duration, :duration_min, :duration_max, :backend_only, :weekend_extra, :_destroy])
end
views/extra_guests/form
<%= simple_form_for [#attraction, #extra_guest] do |f|%>
<%= f.input :age_table, :as => :select, :selected => #age_table.id, :collection => #age_table_list.map {|u| [u.name, u.id]}, :include_blank => false %>
<% f.button :submit %>
Error message + params
Couldn't find AgeTable without an ID
{"utf8"=>"✓",
"_method"=>"patch",
"authenticity_token"=>"l8HMnVIRybZg==",
"extra_guest"=>
{"age_table"=>"104",
"extra_guest_prices_attributes"=>
{"0"=>{"price"=>"1.0", "weekend_extra"=>"", "start_date"=>"2019-10-15", "end_date"=>"20-09-2019", "duration"=>"", "duration_min"=>"", "duration_max"=>"", "_destroy"=>"false", "id"=>"42"},
"1"=>{"price"=>"1.0", "weekend_extra"=>"", "start_date"=>"2019-10-15", "end_date"=>"2019-10-16", "duration"=>"", "duration_min"=>"", "duration_max"=>"", "_destroy"=>"false", "id"=>"43"}}},
"commit"=>"Save new option",
"attraction_id"=>"185",
"id"=>"55"}

Method update returns true or false. You can find docs here. To check errors you need to call method errors on #extra_guest object.
#extra_guest.update(extra_guest_params)
#extra_guest.errors.full_messages

Related

Error when submitting form: Nested attributes unpermitted parameters

I've tried the solutions on this other stack overflow question but they aren't working.
I'm getting this error when submitting my form: Unpermitted parameter: organization_required_fields
Any help would be appreciated.
I have the following models:
class Organization < ActiveRecord::Base
belongs_to :user
has_many :organization_required_fields
has_many :fields, through: :organization_required_fields
accepts_nested_attributes_for :organization_required_fields, allow_destroy: true
end
class OrganizationRequiredField < ActiveRecord::Base
belongs_to :organization
belongs_to :field
end
class Field < ActiveRecord::Base
has_many :organization_required_fields
has_many :organizations, through: :organization_required_fields
end
My controller:
def update
...
#organization.update(organization_params)
...
end
private
def set_organization
#organization = Organization.find_by_id(params[:id])
...
end
def organization_params
params.require(:organization).permit(:name, :user_id, organization_required_fields_attributes: [:id, :organization_id, :field_id, :_destroy])
end
My form view
...
= f.select :organization_required_fields, options_for_select(#fields.collect {|rf| [ rf.name.titleize, rf.id ] }, #organization.fields.collect{ |orf| orf.id }),{ :prompt => "Please select"},{ :multiple => true, :size => 15 }
...
I actually changed a lot by following this rails cast
I also had to change the organization_params to
params.require(:organization).permit(:name, :user_id, { field_ids: []})
You need to use fields_for in your form.

Rails poll app check if vote count for option has reached a value

I am creating an app to poll users. I started from this tutorial and modified it. I also posted another question regarding it here.
Each user has a vote weight. So far users can vote and vote count (calculated based on vote weight of the user) for each option is displayed.
What I am trying to do now is to set a condition that checks if any of the options for that poll has reached 50%.
vote.rb
class Vote < ApplicationRecord
belongs_to :user
belongs_to :vote_option
end
vote_option.rb
class VoteOption < ApplicationRecord
belongs_to :poll
validates :title, presence: true
has_many :users, through: :votes
has_many :votes, dependent: :destroy
def get_vote_count
Vote.joins(:vote_option).joins(:user).where("vote_options.id = #{self.id}").sum(:vote_weight)
end
end
poll.rb
class Poll < ApplicationRecord
validates :question, presence: true
validates :division, presence: true
validates :open_date, presence: true
validates :close_date, presence: true
before_save :set_position
set_sortable :sort, without_updating_timestamps: true
has_many :comments, as: :commentable
has_many :votes, :through => :vote_options
has_many :vote_options, dependent: :destroy
belongs_to :division
belongs_to :user
has_and_belongs_to_many :users
accepts_nested_attributes_for :vote_options, :reject_if => :all_blank, :allow_destroy => true
accepts_nested_attributes_for :users
def normalized_votes_for(option)
votes_summary == 0 ? 0 : (option.get_vote_count.to_f / votes_summary) * 100
end
def votes_summary
vote_options.inject(0) {|summary, option| summary + option.get_vote_count}
end
end
polls_helper.rb
module PollsHelper
def visualize_votes_for(option)
content_tag :div, class: 'progress' do
content_tag :div, class: 'progress-bar',
style: "width: #{option.poll.normalized_votes_for(option)}%" do
"#{option.get_vote_count}"
end
end
end
end
polls_controller show
def show
#poll = Poll.includes(:vote_options).find_by_id(params[:id])
#vote = Vote.find_by_id(params[:id])
#users = #poll.users
#comments = Comment.with_details.all
end
So on polls/show.html.erb I'd need something like:
<% if option.get_vote_count.any > 50 %>
do something
<% end %>
How can I fix the code above to have it working? And what should I add on my polls_controller under show action?
Thanks in advance.
This was the solution. Thanks to #Ash to point me on right direction:
<% #poll.vote_options.each do |option| %>
<% if option.get_vote_count > 50 %>
<h4> Condition met! </h4>
<% end %>
<% end %>

How to combine information from two tables when creating a JSON on Ruby on Rails?

What is the best approach to combine information from two different tables on Ruby on Rails, when building a JSON for Web Services purpose?
I want to combine my list of clients with a tag that is taken from another table than users table.
Here is how I proceed from the controller
def clients
#orders = #bar.orders
#users = User.where(id: #orders.pluck(:user_id).uniq).all
#tags = UserTag.where(bar: #bar, user_id: #orders.pluck(:user_id).uniq).all
end
The view is built this way
json.user_tags do
json.array!(#tags) do |user_tag|
json.extract! user_tag, :id, :bar_id, :user_id, :tag
end
end
json.users do
json.array!(#users) do |user|
json.extract! user, :id, :first_name, :last_name, :email, :facebook_id, :context, :created_at, :updated_at, :company, :phone, :birthdate, :stripe_customer_id, :bar_id, :role
end
end
The JSON generated with this code looks like this
I would like to integrate the tag field directly in users array, next to other users information such as on this illustration
The UserTag model is built like that
class UserTag < ActiveRecord::Base
belongs_to :user, :counter_cache => true
belongs_to :bar
validates_uniqueness_of :bar_id, :user_id, :scope => :bar_id
acts_as_paranoid without_default_scope: true
def self.default_scope
with_deleted
end
def api_error_message
errors.full_messages.join("\n")
end
end
And User model:
class User < ActiveRecord::Base
has_many :access_tokens, dependent: :destroy
belongs_to :club
belongs_to :bar
enum role: [:user, :club_owner, :waiter, :admin]
has_many :club_comments
has_many :club_subscriptions
has_many :artist_subscriptions
has_many :artist_votes
has_many :payments
has_many :carts
has_many :user_entrances
has_many :bookings, through: :user_entrances
has_many :booking_events, through: :user_entrances
has_many :cart_item_consumptions
has_many :clientlist_elements
has_secure_password
has_one :address, as: :addressable
accepts_nested_attributes_for :address
validates :password, length: {minimum: 8}, if: :validate_password?
validates :password_confirmation, presence: true, if: :validate_password?
validates :email, presence: true, if: :user_context_email
validates :email, email: true, if: :user_context_email
validates :email, :facebook_id, uniqueness: true, :allow_blank => true, :allow_nil => true
validates :first_name, presence: true
validates :last_name, presence: true
reverse_geocoded_by :latitude, :longitude
after_create :create_access_token
after_save :update_vote_position_if_needed
def validate_password?
password.present? || password_confirmation.present?
end
def name
"#{first_name.capitalize} #{last_name.capitalize}"
end
def create_access_token
AccessToken.create(user: self)
end
def user_context_email
context == 0
end
def user_context_fb
context == 1
end
def update_vote_position_if_needed
if self.latitude_changed? || self.longitude_changed?
self.delay.update_vote_position
end
end
def update_vote_position
self.artist_votes.each do |vote|
vote.latitude = self.latitude
vote.longitude = self.longitude
vote.save
end
end
def stripe_description
"#{first_name} #{last_name} - #{email}"
end
def stripe_customer_metadata
{"User_id" => self.id, "Firstname" => self.first_name, "Lastname" => self.last_name, "Email" => self.email, "Phone" => self.phone}
end
def api_error_message
errors.full_messages.join("\n")
end
end
EDIT
I tried the #krishnar solution, here is how the JSON looks like now
The users are duplicated and only users with tag appear (we need to display all users even those without tags)
Modify user model to have association:
class User < ActiveRecord::Base
# define user to user_tags association
has_many :user_tags
end
Join users table with user_tags and select user_tags id as tag to use in json file:
def clients
#orders = #bar.orders
#users = User.where(id: #orders.pluck(:user_id).uniq).joins("left join user_tags on users.id=user_tags.user_id and user_tags.bar_id='#{#bar.id}'").select("users.*","user_tags.id as tag")
#tags = UserTag.where(bar: #bar, user_id: #orders.pluck(:user_id).uniq).all
end
Now you can access tag in #users array:
json.users do
json.array!(#users) do |user|
json.extract! user, :id, :first_name, :last_name, :email, :facebook_id, :context, :created_at, :updated_at, :company, :phone, :birthdate, :stripe_customer_id, :bar_id, :role, :tag
end
end

Rails - Nested Strong parameters

I'm trying to create an user register using two models User and profile, nested strong parameters in one controller. when I send parameter I get this error unknown attribute 'profiles_attributes' for User. and I can't create user neither profile :
class User < ActiveRecord::Base
has_one :profile
has_many :apartments
has_many :session
has_secure_password
validates :email, presence: true, uniqueness: true
validates :password, presence: true
accepts_nested_attributes_for :profile
end
class Profile < ActiveRecord::Base
belongs_to :user
belongs_to :city
has_many :profile_universities
has_many :universities, through: :profile_universities
has_many :profile_preferences
has_many :preferences, through: :profile_preferences
has_one :photo, :as => :imageable
end
class Api::V1::UserController < ApplicationController
before_action :user_params
def create_without_facebook
#user= User.new(user_params)
if #user.save
#profile = Profile.new(user_params[:profiles_attributes])
render json: [#user, #profile]
else
render json: #user.errors, status: :unprocessable_entity
end
end
def user_params
params.require(:user).permit(:email, :password, profiles_attributes: [:first_name, :last_name, :birthday, :gender, :marital_status, :ocupation, :budget, :question, :about, :city])
end
end
use the singular profile_attributes if it's a has_one

Nested attributes saving error

I have models
class Survey < ActiveRecord::Base
has_many :questions
acts_as_list
validates :title, :presence =>true
validates :short_description, :presence=>true
validates :description, :presence=>true
end
class Question < ActiveRecord::Base
belongs_to :survey
has_many :options
accepts_nested_attributes_for :options, :reject_if => lambda { |a| a[:title].blank? }, :allow_destroy => true
acts_as_list :scope=>:survey
end
class Option < ActiveRecord::Base
attr_accessible :title, :description, :position
belongs_to :question
acts_as_list :scope=>:survey
end
when i save or update question model it generate an error
#question = Question.new(params[:question])
#question.save
#question = Question.find(params[:id])
#question.update_attributes(params[:question])
In both cases it generates an error
NoMethodError (undefined method `survey_id' for #<Option:0xb332394>):
app/controllers/admin/questions_controller.rb:47:in `block in create'
app/controllers/admin/questions_controller.rb:46:in `create'
I can not understand why it is generating this error, since Option do not have any relation to Survey
Could it be this (on Option):
class Option < ActiveRecord::Base
attr_accessible :title, :description, :position
belongs_to :question
acts_as_list :scope=>:survey # <-- no survey_id ??
end

Resources