Is this the proper way to setup a has_many through association? - ruby-on-rails

So I have 4 models..
A User model, a Question model an Answer model and a User_Question model.
Now I've created default seed questions that apply to all users i.e. #questions = Question.all
And these same questions every user can see, now how can I allow each user to write their own answer to these questions when they aren't directly associated with the question? I was given a solution to create a has_many through association, I just want to make sure I've set it up correctly please see code below, thanks:
user.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :user_questions
has_many :questions, through: :user_questions
end
answer.rb
class Answer < ActiveRecord::Base
attr_accessible :answer
has_many :user_questions
has_many :questions, through: :user_questions
end
question.rb
class Question < ActiveRecord::Base
attr_accessible :title, :body
belongs_to :user
has_one :answer
end
user_question.rb
class UserQuestion < ActiveRecord::Base
belongs_to :user
belongs_to :question
belongs_to :answer
end

If I understand this correctly you say your questions exist independently of users. Yet questions belongs to users.
My understand of this should be as follows:
User.rb
has_many :questions
has_many :answers
question.rb
belongs_to :user
has_many :answers
answer.rb
belongs_to :question
belongs_to :user
Notice the plurals as well for belongs_to and has_many.
The link for the guide is here but I don't think you need user_questions.
http://guides.rubyonrails.org/association_basics.html#the-has-many-association

Related

Access value of foreign-key

I'm working on my own Web-app but I'm facing a problem.
Here is my models :
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :player_seasons
has_many :forecasts, through: :player_seasons
end
class PlayerSeason < ApplicationRecord
belongs_to :user
belongs_to :season
belongs_to :championship
has_many :forecasts
has_many :matches, through: :forecasts
end
class Championship < ApplicationRecord
belongs_to :season
has_many :player_seasons
has_many :users, through: :player_seasons
end
#playerseasons = PlayerSeason.all
I am iterating on: #playerseasons
I would like to compare all the PlayerSeason (#playerseasons) as following :
#playerseasons.each do |playerseason|
if playerseason.championship_id == #playerseason.championship
else
end
end
The idea is comparing all the playerseasons, if a playerseason has the same championship as the current_user, something will appears otherwise something else (basic condition).
But I'm stuck and can't access the exact championship of the current user, on the other side I can access the championship of the playerseasons.
Thank you by advance :)
I did not look critically at database design model which potentially could be done differently. Also I'm taking this as a non-production app as you mention in your question therefore database load optimization is a second priority.
With what you have now I would do something like just to get it to work
user_championships = current_user.player_seasons.map(&:championship).uniq
#playerseasons.each do |playerseason|
if user_championships.include?(playerseason.championship)
else
end
end

Rails best way (or best practices)

I have a model which I don't know how to focus the following issue:
I have been reading the following posts
before_create in rails model
before_create in user model -- set integer based on email (RAILS)
Access current_user in model
I have a project where I want to manage some properties (Assets).
I have Property, Owner, Company and Users.
The House and the Owner are linked in the DB with a FK so 1 Company has N Owners and 1 Company has N Properties.
The model User is linked to Company, so 1 Company has N users.
How can I access the company_id in the model Users in order to store this ID in the Properties and in the Owner model when the Property and Owner is created?
Do I have to do it in the controller and model?
Owner Class
class Owner < ApplicationRecord
acts_as_paranoid
has_many :property_owners
has_many :properties, :through => :property_owners
belongs_to :company
belongs_to :country
accepts_nested_attributes_for :properties
Property Class
class Property < ApplicationRecord
acts_as_paranoid
has_many :property_owners has_many :owners, :through =>
:property_owners
belongs_to :company belongs_to :country
This is the Company
Class Company < ApplicationRecord
has_many :properties
has_many :owners
And the last one is Users
class User < ApplicationRecord
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
before_create :set_default_role, only: :create
belongs_to :country
belongs_to :company
belongs_to :user_role
accepts_nested_attributes_for :company
Considering you have your associations right, in your controller, when a user creates, for example, a house entry:
def create
#property = current_user.company.properties.new(property_params)
....
end
Where current_user can be replaced by the variable containing the user currently logged on and property_params are the strong params, sent to the controller from your form.
Likewise for owner

Resources for Game Match in Rails?

What would be the best way to architect the model relationships and nested resources to build a game with: Users(from devise), Games, Players(join table w/ Games/Users). My problem is Users exist, but Players need to be created at the same time as games. Creating a game also has to create a player, which is possible but feels icky. Is there a better way to do this? I would like to avoid using transactions or filters to create new resources. Thanks.
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable
devise :omniauthable, :omniauth_providers => [:facebook, :twitter]
has_many :games
end
class Player < ActiveRecord::Base
validates :user_id, uniqueness: { scope: :game,
message: "can't join your own game" }
belongs_to :user
belongs_to :game
has_one :board
has_many :ships
end
class Game < ActiveRecord::Base
belongs_to :first_player, class_name: 'Player', foreign_key: 'first_player_id'
belongs_to :second_player, class_name: 'Player', foreign_key: 'second_player_id'
has_one :first_player_board, through: :first_player, source: :board
has_one :second_player_board, through: :second_player, source: :board
end
I ended up solving this by doing away with the player model all together and having Users have_many :games.
class Game < ActiveRecord::Base
belongs_to :first_player, class_name: 'User', foreign_key: 'first_player_id'
belongs_to :second_player, class_name: 'User', foreign_key: 'second_player_id'
has_one :first_player_board, through: :first_player, source: :board
has_one :second_player_board, through: :second_player, source: :board
end

Rails 4: Saving User selections with a Nested Model Form

I'm working on a project where I will need to test users at the end of a section. Using a Nested Model Form I'd like for users to be able to select answers and have those stored. I'm trying to build it out for myself to improve and could use advice from more experienced developers on how to best approach this.
I am assuming that this is many-to-many through relationship and I would need a joining table but I'm unclear on how to surface it to allow users to select their answers. Would I need to create a controller for this new joining table or am I misunderstanding ActiveRecord in this case?
My Models are:
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
class Test < ActiveRecord::Base
has_many :questions, :dependent => :destroy
accepts_nested_attributes_for :questions
end
class Question < ActiveRecord::Base
belongs_to :test
has_many :answers, :dependent => :destroy
accepts_nested_attributes_for :answers
end
class Answer < ActiveRecord::Base
belongs_to :question
end
Any insight/advice on how to best accomplish my goal would be extremely appreciated.
There are different solutions you can try. One way is to set up associations between test and answers through questions.
user.rb
class User < ActiveRecord::Base
has_one :test
end
test.rb
class Test < ActiveRecord::Base
belongs_to :user
has_many :answers, dependent: :destroy
has_many :questions, through: :answers
accepts_nested_attributes_for :answers, allow_destroy: true
end
question.rb
class Question < ActiveRecord::Base
has_many :answers, dependent: :destroy
end
answer.rb
class Answer < ActiveRecord::Base
belongs_to :test
belongs_to :question
end
As for allowing users to select answers, you may need to set up separate associations for an answer to have many selected_answers and many possible_answers through selected_answers. Maybe start with getting tests and answers set up and then move on to selecting answers.

Rails associations - Users has many Users through Comments

I'm trying to design a comment system allowing users to post on other users' pages, through comments.
A user will have a comment on his page, which is posted by another user called "commenter."
1) Is the following code legit/functional/decent design?
2) Is it OK to have a renamed "commenter" user, in conjunction with an un-renamed "user", or should all association names of user always be renamed semantically?
3) Are there better ways to implement this design intent (e.g. not doing a has_many through:)?
class User < ActiveRecord::Base
has_many :comments
has_many :users, through: :comments
has_many :commenters, through: :comments, class_name: 'User'
end
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :commenter, class_name: 'User'
end
NOTE:
I wish to allow users to comment on users, but also on other models, (e.g. characters, celebrities). So I would think having the comments table be used in various has_many through associations is called for.
users has many commenters through comments
characters has many commenters through comments
celebrities has many commenters through comments
I believe your design is not going to work as it is - you are mixing has_many with has_many through. If I were you I would use an approach like this one:
class User < ActiveRecord::Base
has_many :owned_comments, class_name: 'Comments', foreign_key: 'owner_id'
has_many :posted_comments, class_name: 'Comments', foreign_key: 'commenter_id'
end
class Comment < ActiveRecord::Base
belongs_to :owner, class_name: 'User'
belongs_to :commenter, class_name: 'User'
end
have to tried acts_as_commentable gem it give lot of other options as well like public,private comment https://github.com/jackdempsey/acts_as_commentable
I implemented a similar functionality in mongoid and rails. The models were User, Friendship and Request. Its like User sends friend request to another user.
class User
include Mongoid::Document
include Mongoid::Timestamps
devise :invitable, :database_authenticatable, :registerable, :recoverable,
:rememberable, :trackable, :validatable, :confirmable
...
has_many :requests_from, class_name: "Request", inverse_of: :requested_by
has_many :requests_to, class_name: "Request", inverse_of: :requested_to
has_many :friendships, inverse_of: :owner
def friends
#retrive all the friendships and collect users have sent me a request or being sent a request.
fs = Friendship.any_of({:friend_id.in => [self.id]}, {:owner_id.in => [self.id]}).where(state: 'accepted')
User.in(id: fs.collect{|i| [i.friend_id, i.owner_id]}.flatten - [self.id])
end
end#User
class Friendship
include Mongoid::Document
include Mongoid::Timestamps
field :state, type: String, default: 'pending'
field :pending, type: Boolean, default: true
belongs_to :owner, class_name: 'User'
belongs_to :friend, class_name: "User"
validates :state, inclusion: { in: ["pending", "accepted", "rejected"]}
...
end#Friendship
class Request
include Mongoid::Document
include Mongoid::Timestamps
field :state, type: String, default: 'pending'
belongs_to :requested_by, class_name: 'User', inverse_of: :requests_from
belongs_to :requested_to, class_name: 'User', inverse_of: :requests_to
validates :state, inclusion: { in: ["pending", "accepted", "rejected"]}
...
end#Request
I hope this helps.

Resources