Association Issue - ruby

I have 3 models User, Club and Mcq.
In club model. I assign club (class) as -
9-physics
9-chemistry
10-physics
10-chemistry...
Here is my Association
class User < ActiveRecord::Base
has_and_belongs_to_many :clubs
end
class Club < ActiveRecord::Base
has_many :mcqs
has_and_belongs_to_many :users
end
class Mcq < ActiveRecord::Base
belongs_to :club
end
In my student view (student show index) I show all club (as subject) and after click on a subject I just want to show Mcq topic of that related subject.
for that my Club Controller is -
class ClubsController < ApplicationController
#its show subject list
def student_show_index
#club = current_user.clubs
end
#its show topic according to subject.
def student_show_topic
#club = current_user.clubs
#mcq = #club.first.mcqs.order('created_at DESC')
end
end
So my question is, when I click on subject physics it show all the Mcq of 9th. and same for chemistry.
I just want to filtered Mcq according to subject.

You have to send a params as club_id in the link of subject which you are clicking. eg. <%=link_to "Subject", x_path(club_id: n) %> Then you can catch this params in your controller action as params[:club_id]. then rewrite the controller action as following
def student_show_topic
#club = Club.find(params[:club_id])
#mcq = #club.mcqs.order('created_at DESC')
end
Not you may need to permit club_id this params in your controller, if not yet added. Hope this will help you. Let me know if any issues?

Related

Ruby Ohm, how to find a record in a set or collection?

This question is related to other: Many-to-many relationships with Ruby, Redis, and Ohm
I have a Model with a collection and I would like to look for an id. How can I do this?
Models
class User < Ohm::Model
attribute :name
end
class Event < Ohm::Model
attribute :title
collection :attendees, :User
end
Usage
#fran = User.create(name: "Fran")
#event = Event.create(title: "Party in Las Vegas")
#event.attendees.add(#fran)
Event.find(attendees: #fran)
=> Ohm::IndexNotFound exception!
What I would like is to be able to ask by the Users which attending of a Event and what are the Events by an User.
You want a set of all users attending an event, and you also want a set of all events attended by a user. The simplest way would be to create a model Attendee that references both a user and an event:
class Attendee < Ohm::Model
reference :user, :User
reference :event, :Event
end
u = User.create(name: "foo")
e = Event.create(name: "bar")
a = Attendee.create(user: u, event: e)
Attendee.find(user_id: u.id).include?(a) #=> true
Attendee.find(event_id: e.id).include?(a) #=> true
Then if you want all users that attended an event:
Attendee.find(event_id: e.id).map(&:user)
Or all the events attended by a user:
Attendee.find(user_id: e.id).map(&:event)
You can create methods in User and Event as shortcuts for those finders:
class User < Ohm::Model
attribute :name
def events
Attendee.find(user_id: id).map(&:event)
end
end
class Event < Ohm::Model
attribute :name
def visitors
Attendee.find(event_id: id).map(&:user)
end
end
Then:
u.events.include?(e) #=> true
e.visitors.include?(u) #=> true
Let me know if it works for your use case.
I'm not familiar with Ohm but I think you only need to add the index
class Event < Ohm::Model
attribute :title
collection :attendees, :User
index :attendees
end
Then you should be able to do
Event.find(attendees: #fran)
OR
Event.find(attendees: #fran.id)

Get sorted list of the top voted Models from DB

Using: Rails 4.1.4, PostgreSQL 9.1.13
Hi. I'm have a simple problem, but for some reason I can't get it done. The picture is this:
Models
class Article < ActiveRecord::Base
belongs_to :user
has_many :votes
end
class User < ActiveRecord::Base
has_many :articles
has_many :votes
end
class Vote < ActiveRecord::Base
belongs_to :article
belongs_to :user, scope: :hotel_id
validates_inclusion_of :value, in: 0..5
validates_uniqueness_of :user_id, :article_id
end
Idea
Each User can Vote for each Article but only once (to avoid multiple voting).
Vote model has a 'value' attribute that is the range 0..10.
ArticlesController except standard CRUD methods has action #showcase which must return 5 articles with the top votes rating from the DB and sort them in the descending order (and render the respective view).
So I understand that the proper way is to write the class method in the Article Model (smth. like "by_top_votes") and use it in the ArticlesController#showcase:
def showcase
#top_five_articles = Article.by_top_votes
end
The problem is that I can't write the proper query to the DB which will: 1)find articles, 2)find all votes of the each article, 3) sum all values of the respective article's votes, 4)sort them (this step I know how to do).
Thank you for reading and for the help.
P.S. Maybe my way to solve problem is almost wrong. If this so, please tell my the right one.
Ok, I've done it by myself. If anybody will stuck with the same problem, here is solution for it.
1. In Vote model summarize the vote's values:
def self.sum_value
sum(:value)
end
2. Add new attribute (and column) to Article - user_rating:integer.
3. In the Article model define two class methods:
# assign user_rating attribute with the sum of all votes values
def set_user_rating
user_rating = self.votes.sum_value
self.update_attribute(:user_rating, user_rating)
end
# get top 5 articles by user_rating value from db
def self.top_by_user_rating
Article.order(:user_rating).reverse_order.limit(5)
end
4. In the ArticlesController define showcase action:
def showcase
#top_articles = Article.top_by_user_rating
end
5. In the VotesController define create action:
def create
#article = Article.find(params[:article_id])
#vote = #article.votes.create(vote_params)
if #vote.save
#article.set_user_rating
redirect_to #article, notice: "Thanks for your vote"
else
.
end
end
It works and tests are passing.

How to check if model has existing model associations in Rails?

I have two ActiveRecord models (Book, Ad) which are associated. In my query I want to fetch books which has got 1 or more ads. What would be the best way to do this?
# in controller:
#books = Book.where(book has got 1 or more ads).last(20)
# Book model:
class Book < ActiveRecord::Base
has_many :ads, :dependent => :destroy
...
end
# Ad model:
class Ad < ActiveRecord::Base
belongs_to :book
...
end
One option is to use joins:
Book.joins(:ads)
joins allows you to do all of this in one query, and this would give you all Books that have a book_id on Ad set.
So for your controller, you'd have:
#books = Book.joins(:ads).last(20)
in your controller
subquery = Ad.select("book_id").group(:book_id).having("COUNT(*) >= 1").to_sql
#books = Book.where("id IN (#{subquery})").last(20)
Another simple solution would be
Ad.all.map{|ad| ad.book}.uniq.last(20)
This will return the last 20 unique books in an Array because if a Ad exists then it has a Book thus the Book has 1 or more Ads

Rails callback after_save not setting attribute

I'm dealing with a problem on a after_save callback. I'm sure there is a easy solution, but I can't figure it out.
I have 3 models: User, Product, Bid. The Product table contains a boolean field "available", which is set default to true. If a User places a bid, the available field should be set to false.
I thought this should work with a callback on the bid model.
I can access and set the available field in the console by typing:
b = Bid.last
b.product.available = false
=> false
However I can't change it via the controller, so I think it doesn't execute the callback. What am I doing wrong?
Thank you all for your help!
product.rb
class Product < ActiveRecord::Base
has_one :bid
belongs_to :user
end
bid.rb
class Bid < ActiveRecord::Base
attr_accessible :product_id, :user_id, :product
belongs_to :product
belongs_to :user
after_save :set_product_status
def set_product_status
self.product.available = false
end
end
bids_controller.rb
...
def create
#user = current_user
product = Product.find(params[:product_id])
#bid = #user.bids.build(product: product)
respond_to do |format|
if #bid.save
...
Since bid belongs_to product, you should save the product too.
def set_product_status
self.product.available = false
self.product.save
end

ActiveRecord :through to set default values on through table

I would like to set a default value in a has_many through association.
Lets say I have three models:
People
Friends
Dogs
A person can request that a dog becomes their friend.
So a person would create an association where friends has an active column = false.
User
has_many :friends
has_many :dogs, :through => :friends
Now when I assign a dog to a user
User.find(1).dogs << dog
The friends table has null in the active column.
My friends model is defined as
Friend
def initialize(args = {})
super(args)
active = false
end
yet this does not work because the friend object is never created. Do I have to manually create one?
To set default values of a model; In the model I do this
before_save :default_values
private
def default_values
self.status = :active unless self.status
end
Not sure if this is the correct approach though.
With the following code you'll create a new friend with active = false
class User < ActiveRecord::Base
has_many :friends, :conditions => "active = false"
has_many :dogs, :through => :friends
end
#user = User.new
#user.friends.create #or #user.friends.build

Resources