I am trying to create a Rails app and I have a database consisting of author and a quotation by that author.
Now different users can choose to destroy or kill quotations from the database however it must only be deleted for that particular user i.e other users should still be able to see quotes that they didn't delete even if another user did.
I know that I would need to implement cookies but other than that I am unsure how to proceed. Can anyone point me to a tutorial or give me some pointers to get started on this complex task?
You surely have a User model in your application - one 'Rails-like' way to go about this would be to add a has_and_belongs_to_many relationship between User and Quotation.
This creates a relationship between each individual user and 'their' quotations. This relationship can be deleted without actually deleting a quotation, so all quotations would still be available to other users. If you want each user to be able to see all quotations by default, you would need to set up the relationship in advance.
Assuming you are using Devise to log your users in, all you'd need to do then is to replace Quotation.all with current_user.quotations in whichever controller you are using to display quotations.
The Rails guide linked above is quite helpful but basically you just need to add something like the following:
class User
has_and_belongs_to_many :quotations
before_create :add_quotations
def add_quotations
self.quotations << Quotation.all
end
#etc...
end
class Quotation
has_and_belongs_to_many :users
#etc...
end
and then run a migration adding a new table called users_quotations with the columns user_id and quotation_id.
EDIT
As #Yule pointed out this wouldn't let users see any quotations that were created after they were, and it would be quite annoying to have to set up the join tables in advance, so a more efficient way would be to have an excluded_quotations join table instead. So users can see all quotations except the ones that they have excluded.
Related
How do I associate two entries in a database that are connected through a many-to-many relationship in Rails?
I'm trying to associate Users and Issues for an issue tracker. I'm using has_and_belongs_to_many, not :through. I have a :user_id and :issue_id available to me, but there doesn't seem to be User.issues.find(id) or Issue.users.find(id) available to me. I have a route post "/", to: "home#create". I'm trying to make a create method in home_controller.rb.
From the look of it you're calling the method on the User class and not an instance.
If you want to get the issues connected to a user you need to fetch the user first:
User.find(id).issues
If you want to add a record to the association you can use the shovel method or any of the methods generated by the association macro:
User.find(id).issues << Issue.find(3)
User.find(id).issues.push(Issue.find(3))
User.find(id).issue_ids = [1, 2, 3]
Besides that you have a smattering of naming issues in your schema. Use snake_case everywhere in your database schema unless you have a good reason why you want to break the conventions and feel like explicitly configuring table and foreign key names.
I would also really question if you really want to use has_and_belongs_to_many. It should only really be used if you can't foresee that you ever will need to add additional attributes to the join table or never need to query the table directly - it seems pretty unrealistic that that would be true in an issue tracker. You want has_many through: - pretty much always.
I have a route post "/", to: "home#create". I'm trying to make a
create method in home_controller.rb.
Don't throw everything into a junk drawer controller. Think about your app in terms of resources that can be CRUD:ed and create controllers that handle just that resource. You should think about what the relation between a user and an issue is in your domain and how you can model it as an actual entity in the domain logic instead of just plumbing.
Maybe all I need to do is direct you to Rails Guides: Active Record Associations.
There is neither of these
User.issues.find(id)
Issue.users.find(id)
because when you are finding an issue or user by id, you don't use the association. Instead use these:
Issues.find(id)
Users.find(id)
Since the :id is unique this will work and should be what you want.
The only time you want to query issues or users using the association will be when you have the data for the other end of the relationship.
user = User.find(user_id)
issue = user.issues.where(id: issue_id)
Since the :id field is unique, this is the same as Issues.find(id). However if you want to get a collection of a user's issues with some other data, you can put the condition for that data in the where.
You can create an issue for a user this way:
user = User.find(user_id)
issue = User.issues.create( ... )
I would like to create some sample data for a user when they register so that they do not have to start with a blank canvas.
I am presently defining lots of static data in classes which I then iterate over, however setting up relationships is cumbersome and I think that this is quite brittle.
I think that having some demo fixtures (separate from my test set) would be a good way to do this, but as records are tied to an account I can't see how I can insert this data and attach it to the account when loading the fixtures.
This might not even be the best approach, but if there is a better way then please let me know.
Every RAILS application has seeds.rb present in db/ folder.So as the name says,it is used to seed your db by default records that you may want.
So this is how i am using my seeds.rb.Creating many records,constants and then to put those records in your db,just run rake db:seed assuming you have db ready.See HERE for more infor
my seeds.rb
###seed eventype table with default values
["birthday","farewell","party"].each do |f|
EventType.find_or_create_by({name:f.upcase})
end
###create users with random names
##after creating users,create associated fields
%w[mike john paul allen harry betty].each_with_index do |name,index|
#user = User.find_or_create_by({email:"user_#{name}#gmail.com"})
##user has_one address
#user.create_address({:address_2=>"street 1,near berry lane"})
##user has_many pictures
#user.pictures.create!({:title=>"Title of the picture",:picture => File.new("#{Rails.root}/public/images/test.jpg")})
end
You can even use (0..6).each do loop to create n records as you wish in db.
for example:-
(0..100).each do
###create user/pictures etc
end
However you must be careful to follow all validations and create valid record else this wont work.
for example,if in user model,you are expecting username as well,then in seeds.rb,you must pass the username so that it passes the validation easily.
=========================================================================
IF you dont want to use db seed,you can use a callbacks on: :create(i dont prefer observers).Simple example can be :
##in user.rb
after_commit :create_default_account, on: :create
def create_default_account
##assuming user has_one :account
self.build_account({:name=>"Default account"})
end
HOPE IT HELPS
I've created 2 tables, one for users and one for admins.
I created 2 tables as they both collect different information, but I want to be able to allow a sign in using an email address and password from both the admin and user tables via the same form.
Is this possible? I've looked around and people seem to have created 1 users table and added an admin boolean, but I wanted to avoid this and I didn't want to collect unnecessary data if I didn't need to.
Any help and assistance about how to best go around this would be great.
If you are implementing something from scratch, then it is simply a matter of coding it. I think this approach has some inherent flaws and I would avoid it.
If you want to have some segregation on the model side of things, I suggest you use STI. That way there is some shared behaviour/attributes and the distinctions can be coded separately, so you have your protection.
If you have plenty of distinct attributes, I would suggest separating them from your user/admin and creating an "admin_profile" model that belongs_to :admin and a "user_profile" that belongs_to :user.
And to make coding "transparent", you can create accessors in your admin model class to get/set the profile attributes seamlessly. Say you have an is_cool attribute on the admin_profile model, but you'd like to access it as
imadmin.is_cool
You can have in your admin.rb model
has_one :admin_profile
def is_cool
self.admin_profile.is_cool
end
be careful cause the has_one relationship may return nil if there is no profile associated with the admin/user.
I would like to create new tables, add/delete columns from within my app. Is this possible?
Yes, you can do whatever the application database user can do to the database with ActiveRecord::Base.connection.execute. For example:
ActiveRecord::Base.connection.execute('ALTER TABLE people ADD name VARCHAR(60);')
But, if you add a column to a table, the corresponding attribute for the column will not be available in the ActiveRecord class until you restart the application.
No. It is not possible. Rails has to run migrations to get the tables in to the database. This requires that the server has be stopped and restarted after the migrations. You don't want this scenario in production.
Dynamic forms would accomplish what I believe you are after.
In short you make fields of a model a separate model. For instance
class Car
has_many :car_fields
end
class CarFields
belongs_to :car
end
Then you can make a form where the users can add and remove fields when the add a car to the database.
This is great explained by Ryan Bates here http://railscasts.com/episodes/403-dynamic-forms
I think you need a subscription to watch it. I you don't have one, get one. Railscasts is great!
I'm still learning Ruby, and get caught up in alot of the 'magic', wanting to better understand what is actually happening, and making sure that I understand what it is doing.
I've got a user, and each user has entries.
In my user class, I have
has_many :entries
and in my entries class I have
belongs_to :user
I was expecting that the entries table would have a column for users, but I'm not seeing that when I 'describe' the database.
How do I know, or how does Rails know which user the entry is connected to? Or do I need to create a field myself to do that?
It seems strange to me that we have all these 'belongs_to', etc. yet it isn't explicit how that connection is made.
This is a common misconception. Associations do not create the database tables for you. Instead, you have to create them yourself. What you need to be careful of, is that an Entry model would have a user_id field, in order for the association to fully work. I truly would not want to advertise or anything, but i have created a blog post that can help you quite a lot i think :
http://www.codercaste.com/2011/02/06/rails-association-in-plain-english-what-i-wish-i-had-known-before-i-started/