Best approach for creating a polling app in Rails - ruby-on-rails

My models:
class Poll < ActiveRecord::Base
validates_presence_of :title
validates_presence_of :description
has_many :questions, dependent: :destroy
has_many :responses, through: :questions
accepts_nested_attributes_for :questions, reject_if: lambda { |a| a[:title].blank? }, allow_destroy: true
end
class Question < ActiveRecord::Base
belongs_to :poll
has_many :answers, dependent: :destroy
has_many :responses, through: :answers
accepts_nested_attributes_for :answers, reject_if: lambda { |a| a[:content].blank? }, allow_destroy: true
end
class Answer < ActiveRecord::Base
belongs_to :question
has_many :responses
end
class Response < ActiveRecord::Base
belongs_to :answer
end
When you go to /polls/.:id it shows the poll with its corresponding questions and each question with its corresponding answers.
I've been playing around with this answer but I don't know what to do from there. I want whomever I send a poll link (/polls/.:id) to to be able to answer that poll. The method described in the answer linked before creates a form for each question.

I'd check out the documentation on rails views here:
http://guides.rubyonrails.org/action_view_overview.html
There is tons of documentation on how to access and transport data with various form elements.

Related

Trying to match Products and Requests through Categories

I'm making a rails marketplace app for uni where Users can be matched with specific products based on their request.
Users can list products that have specific categories.
Users can also list Requests where they can specify what products they're looking and their categories.
The aim is to match the request to a particular product based on the matching categories
Here are my models
class Product < ApplicationRecord
belongs_to :user
has_many_attached :images, dependent: :destroy
has_many :product_categories
has_many :categories, through: :product_categories
validates :user_id, presence: true
end
class Category < ApplicationRecord
has_many :product_categories
has_many :products, through: :product_categories
validates :name, presence: true, length: { minimum: 3, maximum: 25}
validates_uniqueness_of :name
end
class ProductCategory < ApplicationRecord
belongs_to :product
belongs_to :category
end
class Request < ApplicationRecord
belongs_to :user
has_many_attached :images, dependent: :destroy
has_many :request_categories
has_many :categories, through: :request_categories
validates :user_id, presence: true
end
class RequestCategory < ApplicationRecord
belongs_to :request
belongs_to :category
end
I was thinking of creating a new model called Match to bring together the product and categories or is it easier to match it in the request?
In my mind, your new Match class would essentially be a join table for a has_many :through association. Assuming that you're implementing an asynchronous worker (e.g. Sidekiq / ActiveJob) to go through and make "matches", you'll want to connect matches to a particular Request, and likely store some meta-data (has the user seen the Match yet? Have they rejected it?)
So, I'd probably generate a Match class like this:
rails g model Match seen_at:datetime deleted_at:datetime request:references product:references
And set up the associations as follows:
class Match < ApplicationRecord
belongs_to :request
belongs_to :product
end
class Request < ApplicationRecord
belongs_to :user
has_many_attached :images, dependent: :destroy
has_many :request_categories
has_many :categories, through: :request_categories
has_many :matches
has_many :products, through: :matches
validates :user_id, presence: true
end
class Product < ApplicationRecord
belongs_to :user
has_many_attached :images, dependent: :destroy
has_many :product_categories
has_many :categories, through: :product_categories
has_many :matches
has_many :requests, through: :matches
validates :user_id, presence: true
end
Also, you'll likely want to add the Request has_many :through to your Category model (I think you forgot that one):
class Category < ApplicationRecord
has_many :product_categories
has_many :products, through: :product_categories
has_many :request_categories
has_many :requests, through: :request_categories
validates :name, presence: true, length: { minimum: 3, maximum: 25}
validates_uniqueness_of :name
end
The big part of the job is working out how to have your app periodically look for matches - you may want to start with the Active Job Basics documentation.

Rails: Passing nested attributes to vue.js

I have a Survey model
class Survey < ApplicationRecord
has_many :questions, dependent: :destroy
accepts_nested_attributes_for :questions, allow_destroy: true
belongs_to :user
end
And Quesiton model which is nested to "survey" as below;
class Question < ApplicationRecord
enum qtype: [:multiple_choice, :check_boxes, :short_answer]
belongs_to :survey
has_many :options
accepts_nested_attributes_for :options, allow_destroy: true
end
And option model connected to question as nested.
class Option < ApplicationRecord
belongs_to :question
end
Parameters in my surveys_controller:
def survey_params
params.require(:survey).permit(:name, questions_attributes:[:id, :title, :qtype, :_destroy, options_attributes:[:id, :otext, _destroy]])
end
It is working clear Without Vue.js implementing.
I want to use vue.js for making dynamic form.
What should i do passing do form all nested attributes Without using 'gon' gem
also which json file should i create with jbuilder?
Thanks

Reject nested assosciation creation rails

I have 2 models as below,
Updated based on suggestions
class User < ActiveRecord::Base
has_many :company_users, dependent: :destroy, inverse_of: :user
accepts_nested_attributes_for :company_users, allow_destroy: true
has_many :companies, through: :company_users
has_many :roles, through: :company_users
end
and
class CompanyUser < ActiveRecord::Base
belongs_to :company
belongs_to :role
belongs_to :user, inverse_of: :company_users
validates :user, uniqueness: {scope: [:company, :role]}
end
I find the uniqueness validation is working only on the update request. On create request validation is not functioning and it simply bypasses it.
I want to enable the same validation to reject if a user has same company & role assigned more than once.
If you want a ensure the uniqueness of user on unique pair of :company and :role, then you can try following. By default, the validations run for both create and update. You don't need :on => [ :create, :update ]. So it should be just:
validates :user, uniqueness: {scope: [:company, :role]}
Solved this issue with the below validation,
class User < ActiveRecord::Base
has_many :company_users, dependent: :destroy, inverse_of: :user
accepts_nested_attributes_for :company_users, allow_destroy: true
has_many :companies, through: :company_users
has_many :roles, through: :company_users
validate :company_users, :uniqueness_of_company_users
end
private
def uniqueness_of_company_users
errors.add(:company_users, 'error in role creation') if company_users.map{|x| "#{x.company_id} #{x.role_id}"}.uniq.size != company_users.size
end
This is the additional validation required to solve the issue
Thanks Rich Peck for this https://railscoding.wordpress.com/2015/04/27/uniqueness-gotcha/
From the docs
The :on option takes one of the values :create or :update
--
A validation is only run on create or update anyway, right?
find doesn't manipulate the db, destroy gets rid of the record & new just invokes a new instance of the object. You have literally zero other reasons to validate.
So, really, you should have:
validates :user, uniqueness: {scope: [:company_id, :role_id]}
This will look up against the values in company_id and role_id, which is probably going to be more efficient than calling the company and role objects themselves.
I could be wrong, but I really think if you used the above, it should work.
--
You may also wish to clean up your models:
class User < ActiveRecord::Base
has_many :company_users, dependent: :destroy, inverse_of: :user
accepts_nested_attributes_for :company_users, allow_destroy: true
has_many :companies, through: :company_users
has_many :roles, through: :company_users
end
class CompanyUser < ActiveRecord::Base
belongs_to :company
belongs_to :role
belongs_to :user, inverse_of: :company_users
validates :user, uniqueness: {scope: [:company_id, :role_id]}
end

Allow user to choose correct answer with accepts_nested_attributes_for?

I have the rails relations:
class Quiz < ActiveRecord::Base
has_many :questions, dependent: :destroy
accepts_nested_attributes_for :questions,
reject_if: proc { |a| a[:content].blank? },
allow_destroy: true
end
class Question < ActiveRecord::Base
belongs_to :quiz
has_many :answers, dependent: :destroy
accepts_nested_attributes_for :answers,
reject_if: proc { |a| a[:content].blank? },
allow_destroy: true
end
class Answer < ActiveRecord::Base
belongs_to :question
end
How would a structure the model so when the user is in Quiz#edit or Quiz#new they can select which answer (with radio buttons) is the correct answer?
In the answers table, add an additional attribute called 'is_correct_answer' that will be true only for one combination.

Nested attributes reject_if model has more than four children

I have the below scenario:
class Question < ActiveRecord::Base
has_many :answers, :dependent => :destroy
accepts_nested_attributes_for :answers, :allow_destroy => true, :reject_if => ""
end
class Answer < ActiveRecord::Base
belongs_to :question
end
How can I reject the creation if one question has more than 4 answers?
I hope it work for you.
class Question < ActiveRecord::Base
has_many :answers, :dependent => :destroy
accepts_nested_attributes_for :answers, :reject_if => -> {|q| q['answers'].count > 4}, :allow_destroy => true
end
class Answer < ActiveRecord::Base
belongs_to :question
end

Resources