I want that if a user has ordered a meal, he can talk to the meal provider... and vice versa...
Users can provide meals and order meals too, like on air bnb you can be a guest or a host (or both)
Exemples:
Lets say we have Bob(buyer) who orders a meal from John(maker) I want that John and Bob can chat together
John(buyer) orders a meal from Mike(maker), John and Mike can chat together.
conversations/index.html.erb
<% #users.each do |user| %>
<%= link_to user.full_name , conversations_path(user_id: user), remote: true, method: :post %>
<% end %>
user.rb (I have doubt in this model...)
has_many :meals #Meals that the user offers
has_many :received_orders, class_name: "Order" #The user receive an order
has_many :placed_orders, through: :meals, class_name: "Order" #The user order a meal
has_many :prepared_orders, through: :received_orders, class_name: "Meal", source: :meal #The user has prepared the order
####maybe this way below....TODO
# has_many :meals
# has_many :orders_as_a_customer, class_name: "Order"# same as: has_many :orders
# has_many :orders_as_a_seller, through: :orders_as_a_customer, class_name: "Meal", source: :meal
# has_many :orders, through: :meals
order.rb
class Order < ApplicationRecord
before_save :calculate_price
belongs_to :user
belongs_to :meal
has_many :notifications, as: :topic
monetize :amount_cents, as: :amount
def payment
self.payment_status = true
self.save
end
def calculate_price
self.amount = (self.quantity * meal.price)
end
end
Well I've followed this tutorial to create my chat, and I bet it's possible to adjust to my app to it...
conversation.rb
class Conversation < ApplicationRecord
has_many :messages, dependent: :destroy
belongs_to :sender, foreign_key: :sender_id, class_name: "User"
belongs_to :recipient, foreign_key: :recipient_id, class_name: "User"
validates :sender_id, uniqueness: { scope: :recipient_id }
scope :between, -> (sender_id, recipient_id) do
where(sender_id: sender_id, recipient_id: recipient_id).or(
where(sender_id: recipient_id, recipient_id: sender_id)
)
end
def self.get(sender_id, recipient_id)
conversation = between(sender_id, recipient_id).first
return conversation if conversation.present?
create(sender_id: sender_id, recipient_id: recipient_id)
end
def opposed_user(user)
user == recipient ? sender : recipient
end
end
conversations_controller.rb
class ConversationsController < ApplicationController
def create
#conversation = Conversation.get(current_user.id, params[:user_id])
add_to_conversations unless conversated?
respond_to do |format|
format.js
end
end
def index
session[:conversations] ||= []
#users = User.all.where.not(id: current_user)
#conversations = Conversation.includes(:recipient, :messages).find(session[:conversations])
end
def close
#conversation = Conversation.find(params[:id])
session[:conversations].delete(#conversation.id)
respond_to do |format|
format.js
end
end
private
def add_to_conversations
session[:conversations] ||= []
session[:conversations] << #conversation.id
end
def conversated?
session[:conversations].include?(#conversation.id)
end
end
my actual schema.rb
ActiveRecord::Schema.define(version: 20170629192651) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "attachinary_files", force: :cascade do |t|
t.string "attachinariable_type"
t.integer "attachinariable_id"
t.string "scope"
t.string "public_id"
t.string "version"
t.integer "width"
t.integer "height"
t.string "format"
t.string "resource_type"
t.datetime "created_at"
t.datetime "updated_at"
t.index ["attachinariable_type", "attachinariable_id", "scope"], name: "by_scoped_parent", using: :btree
end
create_table "categories", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "conversations", force: :cascade do |t|
t.integer "recipient_id"
t.integer "sender_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "order_id"
t.index ["order_id"], name: "index_conversations_on_order_id", using: :btree
t.index ["recipient_id", "sender_id"], name: "index_conversations_on_recipient_id_and_sender_id", unique: true, using: :btree
end
create_table "ingredients", force: :cascade do |t|
t.string "name"
t.integer "meal_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["meal_id"], name: "index_ingredients_on_meal_id", using: :btree
end
create_table "meals", force: :cascade do |t|
t.string "menu_name"
t.integer "portion"
t.date "availability"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.integer "category_id"
t.string "images"
t.string "location"
t.float "latitude"
t.float "longitude"
t.integer "price"
t.index ["user_id"], name: "index_meals_on_user_id", using: :btree
end
create_table "messages", force: :cascade do |t|
t.text "body"
t.integer "user_id"
t.integer "conversation_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["conversation_id"], name: "index_messages_on_conversation_id", using: :btree
t.index ["user_id"], name: "index_messages_on_user_id", using: :btree
end
create_table "notifications", force: :cascade do |t|
t.boolean "read", default: false
t.string "content"
t.integer "user_id"
t.string "topic_type"
t.integer "topic_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "order_id"
t.index ["order_id"], name: "index_notifications_on_order_id", using: :btree
t.index ["topic_type", "topic_id"], name: "index_notifications_on_topic_type_and_topic_id", using: :btree
t.index ["user_id"], name: "index_notifications_on_user_id", using: :btree
end
create_table "orders", force: :cascade do |t|
t.text "message"
t.boolean "payment_status", default: false
t.integer "quantity"
t.integer "user_id"
t.integer "meal_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "amount_cents", default: 0, null: false
t.json "payment"
t.index ["meal_id"], name: "index_orders_on_meal_id", using: :btree
t.index ["user_id"], name: "index_orders_on_user_id", using: :btree
end
create_table "reviews", force: :cascade do |t|
t.integer "rating"
t.text "comment"
t.integer "meal_id"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["meal_id"], name: "index_reviews_on_meal_id", using: :btree
t.index ["user_id"], name: "index_reviews_on_user_id", using: :btree
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "provider"
t.string "uid"
t.string "facebook_picture_url"
t.string "first_name"
t.string "last_name"
t.string "token"
t.datetime "token_expiry"
t.string "nickname"
t.string "avatar"
t.index ["email"], name: "index_users_on_email", unique: true, using: :btree
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
end
add_foreign_key "conversations", "orders"
add_foreign_key "meals", "users"
add_foreign_key "messages", "conversations"
add_foreign_key "messages", "users"
add_foreign_key "notifications", "orders"
add_foreign_key "notifications", "users"
add_foreign_key "orders", "meals"
add_foreign_key "orders", "users"
add_foreign_key "reviews", "meals"
add_foreign_key "reviews", "users"
end
Concluding from the comments, you'd need to have different models. Here are the ones that make sense to me:
class User < ApplicationRecord
has_many :meals
has_many :orders
has_many :sent_messages, :class => 'ChatMessage', :foreign_key => 'sender_id'
has_many :received_messages, :class => 'ChatMessage', :foreign_key => 'receiver_id'
end
class Meal < ApplicationRecord
belongs_to :user
belongs_to :order_item
end
class Order < ApplicationRecord
belongs_to :user
has_many :order_items
end
class OrderItem < ApplicationRecord
belongs_to :order
has_one :meal
end
class ChatMessage < ApplicationRecord
belongs_to :sender, :class => 'User'
belongs_to :receiver, :class => 'User'
end
Related
migrate file exists but no model for rails application.There are user and book model.I created join table between user and book model.
I write console : rails g migration CreateJoinTableBooksUsers books users
rake:db migrate
**schema.rb**
create_table "books", force: :cascade do |t|
t.string "title"
t.string "author"
t.integer "page_count"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.boolean "status"
t.string "user_id"
t.boolean "barter_status"
end
create_table "books_users", id: false, force: :cascade do |t|
t.bigint "book_id", null: false
t.bigint "user_id", null: false
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.string "username"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
t.index ["username"], name: "index_users_on_username", unique: true
end
add_foreign_key "comments", "books"
add_foreign_key "comments", "users"
end
**migrate**
class CreateJoinTableBooksUsers < ActiveRecord::Migration[6.0]
def change
create_join_table :books, :users do |t|
t.index [:book_id, :user_id]
t.index [:user_id, :book_id]
end
end
end
A migration creates the tables in the database but doesn't create anything else.
But, for a true join table, you don't need a model:
https://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association
# app/models/user.rb
class User < ApplicationRecord
has_and_belongs_to_many :books
end
# app/models/books.rb
class Book < ApplicationRecord
has_and_belongs_to_many :users
end
IF you need scopes, callbacks, or methods on BooksUsers, you can use the has_many :through option:
https://guides.rubyonrails.org/association_basics.html#choosing-between-has-many-through-and-has-and-belongs-to-many
# app/models/user.rb
class User < ApplicationRecord
has_many :books_users
has_many :books, through: :books_users
end
# app/models/books.rb
class Book < ApplicationRecord
has_many :books_users
has_many :users, through: :books_users
end
In this case, you'll need to generate a model:
rails generate model BooksUsers
I have a question about reaching across multiple association levels, if anyone could help me out?
I have a warehouse, and I'm trying to call up an inventory of products by their tag numbers. So far I can through and use methods defined in the Tag model, and grab associated Product name attributes easily enough:
#Warehouse.rb
has_many :tags, as: :location
has_many :products, through: :tags
#Tag.rb
belongs_to product #
#polymorphic
belongs_to :trackable, polymorphic: true
belongs_to :location, polymorphic: true
Now when I try to get the primary category of that inventory item (belongs_to :product), I keep running into issues; I want to define the category in my iterative inventory list, and have the option to sort/group by it:
#Product.rb
has_one :primary_category_assignment
has_many :rfid_tags, as: :trackable
Each product is assigned to a category - associations are warehouses > tags > products > category_assignment > category. I'm trying to drill down to the level of the last two.
#CategoryAssignment.rb #this is a join table
belongs_to :product, required: true
belongs_to :category, required: true
#Category.rb
has_many :products, through: :category_assignment
Here's some of the accompanying code I'm using to get this set up:
#warehouse_controller.rb
def index
#tags = #warehouse.tags.all.joins(:ancestor_product)
end
#warehouses/index.html.erb
<p><% #tags.each do |tag| %>
tag: <%= tag.number %>,
location_id <%= tag.location_id %>,
<%= tag.product.name %>,
Purchased at $<%= tag.product.purchase_price %></p> #grabs an attribute from the product level
#Next level would reach through the category assignment join table (category_id) to grab the category, or at least order by the category assignment
Schema below for reference:
#schema
create_table "categories", force: :cascade do |t|
t.string "name", null: false
t.text "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "position"
end
add_index "categories", ["position"], name: "index_categories_on_position", using: :btree
create_table "category_assignments", force: :cascade do |t|
t.integer "product_id"
t.integer "category_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "primary", default: false
end
create_table "products", force: :cascade do |t|
t.string "name", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.float "purchase_price"
t.text "description"
t.datetime "purchase_date"
end
add_index "category_assignments", ["category_id"], name: "index_category_assignments_on_category_id", using: :btree
add_index "category_assignments", ["product_id"], name: "index_category_assignments_on_product_id", using: :btree
create_table "tags", force: :cascade do |t|
t.string "number", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "location_type"
t.integer "location_id"
t.string "trackable_type"
t.integer "trackable_id"
t.integer "product_id"
end
add_index "tags", ["product_id"], name: "index_rfid_tags_on_ancestor_product_id", using: :btree
add_index "tags", ["location_id"], name: "index_tags_on_location_id", using: :btree
add_index "tags", ["location_type"], name: "index_tags_on_location_type", using: :btree
add_index "tags", ["trackable_id"], name: "index_tags_on_trackable_id", using: :btree
add_index "tags", ["trackable_type"], name: "index_tags_on_trackable_type", using: :btree
add_index "tags", ["user_id"], name: "index_tags_on_user_id", using: :btree
create_table "warehouses", force: :cascade do |t|
t.string "name", null: false
end
I created the following Active Record Schema using migrations but the relationships don't correspond to the schema. I've tried resetting, dropping, creating and migrating but in Rails C if i create a User u.User.create!(...), and then query u.groups or u.genres I get 'undefined method'
Thanks for your help
ActiveRecord::Schema.define(version: 20180603211047) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "genres", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "tag"
t.bigint "user_id"
t.index ["user_id"], name: "index_genres_on_user_id"
end
create_table "genres_users", id: false, force: :cascade do |t|
t.bigint "user_id", null: false
t.bigint "genre_id", null: false
end
create_table "groups", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "name"
t.bigint "user_id"
t.index ["user_id"], name: "index_groups_on_user_id"
end
create_table "groups_users", id: false, force: :cascade do |t|
t.bigint "user_id", null: false
t.bigint "group_id", null: false
end
create_table "playlists", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "name"
t.string "link"
t.text "description"
t.bigint "group_id"
t.index ["group_id"], name: "index_playlists_on_group_id"
end
create_table "users", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.string "name"
t.string "token"
t.date "birthday"
t.string "link"
t.string "playlistId"
t.string "country"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
add_foreign_key "genres", "users"
add_foreign_key "groups", "users"
add_foreign_key "playlists", "groups"
end
here are the models:
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
#before_action :authenticate_user!
has_and_belongs_to_many :genres, :through => :genres_users
has_and_belongs_to_many :groups, :through => :groups_users
include Enumerable
end
class Genre < ApplicationRecord
has_and_belongs_to_many :users, :through => :genres_users
end
class Group < ApplicationRecord
has_and_belongs_to_many :users, :through => :groups_users
has_one :playlist
end
class Playlist < ApplicationRecord
belongs_to :group
end
The relationship is that Groups have users, users have genres (favourite genres!), these are has and belongs to relationships through join tables (multiple genres per user and multiple groups per user). Every group has a playlist, and there will be multiple playlists
[Edited after clarification from OP]
The relationship is that Groups have users, users have genres (favourite genres!), these are has and belongs to relationships through join tables (multiple genres per user and multiple groups per user). Every group has a playlist, and there will be multiple playlists
First off, you don't need a user_id column on groups or genres as that's not how the setup should work.
class Genre < ApplicationRecord
has_many :favorite_genres
has_many :users, through: :favorite_genres
[... other stuff]
end
class User < ApplicationRecord
has_many :group_memberships
has_many :groups, through: :group_memberships
has_many :favorite_genres
has_many :users, through: :favorite_genres
[... other stuff]
end
class Group < ApplicationRecord
has_many :group_memberships
has_many :users, through: :group_memberships
has_many :playlists
[... other stuff]
end
class Playlist < ApplicationRecord
belongs_to :group
end
class GroupMemberships < ApplicationRecord
belongs_to :user
belongs_to :group
[... other stuff]
end
class FavoriteGenres < ApplicationRecord
belongs_to :user
belongs_to :genre
[... other stuff]
end
So you'd drop the user_id column in groups. The connection happens in :group_memberships (the table formerly known as users_groups), which is a user_id, a group_id, and then you can have additional metadata columns as you need them (e.g. admin boolean/role, etc)
. This is called a "Has Many Through" relationship (http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association)
Likewise, a user's favorite genres is setup with a through relationship. So you'll have a separate database table AND model file for those through joins.
I don't think you need your add_foreign_key calls at all at this level, nor many of your indexes. You'll probably do more eager loading or possibly add indexes on the thorugh join tables and you'd do those like this in the schema:
t.index ["user_id", "genre_id"], name: "index_favorite_genres_on_user_id_and_genre_id"
Remember that belongs_to now creates a validation for that to be present in 5.x. You can override this by adding optional: true on that line in the model, e.g. belongs_to :foo, optional: true
So all that being said, here's your new schema:
create_table "genres", id: :serial, force: :cascade do |t|
t.string "tag"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "groups", id: :serial, force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "favorite_genres", id: false, force: :cascade do |t|
t.bigint "user_id", null: false
t.bigint "genre_id", null: false
end
create_table "groups_memberships", id: false, force: :cascade do |t|
t.bigint "user_id", null: false
t.bigint "group_id", null: false
end
create_table "playlists", id: :serial, force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "name"
t.string "link"
t.text "description"
t.bigint "group_id"
t.index ["group_id"], name: "index_playlists_on_group_id"
end
create_table "users", id: :serial, force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.string "name"
t.string "token"
t.date "birthday"
t.string "link"
t.string "playlistId"
t.string "country"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
Give that a whirl (I haven't built this in an app, so there may be some errors in the code) and you should now be able to do your console run:
u = User.create([values])
u.genres (should return nil until you create some relationships)
etc.
[question solved] => I just made a silly mistake and forgot to add #match.save at the end of my method :)
I'm relatively new to RoR and the ActiveRecord architecture. I'm trying to build a simple app that can match 2 users together based on their interests. First here's the schema of my database:
Link to my DB's schema
or if you prefer here's the schema.rb file:
ActiveRecord::Schema.define(version: 20160612080318) do
create_table "conversations", force: :cascade do |t|
t.integer "user1_id"
t.integer "user2_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "conversations", ["user1_id"], name: "index_conversations_on_user1_id", using: :btree
add_index "conversations", ["user2_id"], name: "index_conversations_on_user2_id", using: :btree
create_table "interests", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "matches", force: :cascade do |t|
t.integer "user1_id"
t.integer "user2_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "matches", ["user1_id"], name: "index_matches_on_user1_id", using: :btree
add_index "matches", ["user2_id"], name: "index_matches_on_user2_id", using: :btree
create_table "messages", force: :cascade do |t|
t.text "content"
t.integer "conversation_id"
t.integer "user_id"
t.datetime "read_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "messages", ["conversation_id"], name: "index_messages_on_conversation_id", using: :btree
add_index "messages", ["user_id"], name: "index_messages_on_user_id", using: :btree
create_table "user_interests", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.integer "interest_id"
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "first_name"
t.string "last_name"
t.integer "age"
t.string "avatar_url"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
add_foreign_key "messages", "conversations"
add_foreign_key "messages", "users"
add_foreign_key "user_interests", "interests"
add_foreign_key "user_interests", "users"
end
Just to test my models I didn't take into account the algorithm that will match users based on their interest. So here's my matches_controller.rb:
class MatchesController < ApplicationController
def new
#match = Match.new
end
def create
#match = Match.new(match_params)
#match.user1_id = current_user.id
#match.user2_id = User.first.id
end
private
def match_params
params.require(:match).permit(:user1_id, :user2_id)
end
end
my match model:
class Match < ActiveRecord::Base
belongs_to :user1, class_name: "User"
belongs_to :user2, class_name: "User"
end
and finally my user model:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :user_interests, dependent: :destroy
has_many :interests, through: :user_interests, dependent: :destroy
has_many :messages, dependent: :destroy
has_many :matches, dependent: :destroy
def conversations
Conversation.includes(:messages)
.where("user1_id = :id OR user2_id = :id", id: id)
.order("messages.created_at DESC")
end
def other_user(conversation)
conversation.users.include?(self) ? conversation.other_user(self) : nil
end
def unread_conversations
conversations.select { |c| c.unread_messages?(self) }
end
def unread_conversations_count
unread_conversations.count
end
def unread_conversations?
unread_conversations_count > 0
end
def one_avatar_url
avatar_url ? avatar_url : "http://placehold.it/64x64"
end
end
I've tried to test my Match.create method in the console but got only nil for user1_id and user2_id. I've been looking all day long everywhere without being able to pinpoint what's wrong with my code.
Thanks a lot for helping me on this issue :)
I am writing a Rails 4.2 app with models user, notecard, tag and tagging (for the m-2-m relationship).
A tag can have multiple notecards and a notecard can have multiple tags.
A card belongs to a user and a tag DOESN'T belong to a user.
How can I scope the tags that only a user has used?
I want to have an index of all tags and an index of the tags a user has actually used.
Thanks!
Here is the schema, as I don't have an idea on how to implement the where clause to index the tags a user has used.
to give you an idea, I'm looking for something like this
def index_of_used_tags
#Take all tags, return those that have cards from this user
end
class User < ActiveRecord::Base
has_many :comments
has_many :folders
has_many :cards
end
class Tag < ActiveRecord::Base
has_many :taggings
has_many :cards, through: :taggings
validates_presence_of :name
validates_uniqueness_of :name
end
class Folder < ActiveRecord::Base
belongs_to :user
validates_presence_of :name
validates_uniqueness_of :name, scope: :user_id
end
class Card < ActiveRecord::Base
belongs_to :user
belongs_to :folder
has_many :taggings
has_many :tags, through: :taggins
end
ActiveRecord::Schema.define(version: 20150604113358) do
enable_extension "plpgsql"
create_table "cards", force: :cascade do |t|
t.string "object"
t.text "content"
t.string "source"
t.integer "user_id"
t.integer "folder_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "cards", ["folder_id"], name: "index_cards_on_folder_id", using: :btree
add_index "cards", ["user_id"], name: "index_cards_on_user_id", using: :btree
create_table "comments", force: :cascade do |t|
t.text "content"
t.string "commentable_type"
t.integer "commentable_id"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "comments", ["user_id"], name: "index_comments_on_user_id", using: :btree
create_table "folders", force: :cascade do |t|
t.string "name"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "folders", ["user_id"], name: "index_folders_on_user_id", using: :btree
create_table "taggings", force: :cascade do |t|
t.integer "card_id"
t.integer "tag_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "taggings", ["card_id"], name: "index_taggings_on_card_id", using: :btree
add_index "taggings", ["tag_id"], name: "index_taggings_on_tag_id", using: :btree
create_table "tags", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "users", force: :cascade do |t|
t.string "fname"
t.string "lname"
t.boolean "admin", default: false
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
add_foreign_key "cards", "folders"
add_foreign_key "cards", "users"
add_foreign_key "comments", "users"
add_foreign_key "folders", "users"
add_foreign_key "taggings", "cards"
add_foreign_key "taggings", "tags" end
You can set up a has_many through relationship between User and Tag
class User < ActiveRecord::Base
has_many :comments
has_many :folders
has_many :cards
has_many :tags, through: :cards
end
Then user.tags would give you all the tags the user has used.
User.includes(:cards => :taggings).where('users.id = ?', current_user.id)
Try this query