I'm trying to create a simple # mentions model similar to twitters for my app. I've started building it, but I don't know how I would handle the actual creation of the mention. I need some way to scan let's say a status before it's created for any # symbols, then checking the text following against the database for any matching usernames. If there's a match then a mention gets created along with the status. Can someone point me in the right direction?
Here's what I have so far:
db/migrate/create_mentions.rb
class CreateMentions < ActiveRecord::Migration
def change
create_table :mentions do |t|
t.belongs_to :mentionable, polymorphic: true
t.timestamps
end
add_index :mentions, [:mentionable_id, :mentionable_type]
end
end
models/mention.rb
class Mention < ActiveRecord::Base
belongs_to :mentionable, polymorphic: true
end
models/status.rb
class Status < ActiveRecord::Base
attr_accessible :content
has_many :mentions, dependent: :destroy
end
models/member.rb
class Member < ActiveRecord::Base
has_many :mentions, as: :mentionable, dependent: :destroy
end
controllers/mentions_controller.rb
class MentionsController < ApplicationController
before_filter :authenticate_member!
before_filter :load_mentionable
before_filter :find_member
def new
#mention = #mentionable.mentions.new
end
def create
#mention = #mentionable.mentions.new(params[:mention])
respond_to do |format|
if #mention.save
format.html { redirect_to :back }
else
format.html { redirect_to :back }
end
end
end
private
def load_mentionable
klass = [Status].detect { |c| params["#{c.name.underscore}_id"] }
#mentionable = klass.find(params["#{klass.name.underscore}_id"])
end
def find_member
#member = Member.find_by_user_name(params[:user_name])
end
end
config/routes.rb
resources :statuses do
resources :mentions
end
Thanks to this question: parse a post for #username I was able to get this working. My set up:
db/migrate/create_mentions.rb
class CreateMentions < ActiveRecord::Migration
def change
create_table :mentions do |t|
t.belongs_to :mentionable, polymorphic: true
t.belongs_to :mentioner, polymorphic: true
t.integer :status_id
t.integer :comment_id
t.timestamps
end
add_index :mentions, [:mentionable_id, :mentionable_type], :name => "ments_on_ables_id_and_type"
add_index :mentions, [:mentioner_id, :mentioner_type], :name => "ments_on_ers_id_and_type"
end
end
models/mention.rb
class Mention < ActiveRecord::Base
attr_accessible :mentioner_id, :mentioner_type, :mentionable_type, :mentionable_id, :status_id, :comment_id
belongs_to :mentioner, polymorphic: true
belongs_to :mentionable, polymorphic: true
end
models/member.rb
class Member < ActiveRecord::Base
has_many :mentions, as: :mentionable, dependent: :destroy
end
models/status.rb
class Status < ActiveRecord::Base
attr_accessor :mention
has_many :mentions, as: :mentioner, dependent: :destroy
after_save :save_mentions
USERNAME_REGEX = /#\w+/i
private
def save_mentions
return unless mention?
people_mentioned.each do |member|
Mention.create!(:status_id => self.id, :mentioner_id => self.id, :mentioner_type => 'Status', :mentionable_id => member.id, :mentionable_type => 'Member')
end
end
def mention?
self.content.match( USERNAME_REGEX )
end
def people_mentioned
members = []
self.content.clone.gsub!( USERNAME_REGEX ).each do |user_name|
member = Member.find_by_user_name(user_name[1..-1])
members << member if member
end
members.uniq
end
end
config/routes.rb
resources :statuses do
resources :mentions
end
helpers/mentions_helper.rb
module MentionsHelper
def statuses_with_mentions(status)
status.content_html.gsub(/#\w+/).each do |user_name|
member = Member.find_by_user_name(user_name[1..-1])
if member
link_to user_name, profile_path(member.user_name)
else
user_name
end
end
end
end
Related
I have implemented a Follower/Following Relationship,i want to extend the functionality ,i.e. in my current implementation User 'A' follows User 'B' without the acknowledgement of User 'B'.I want User 'A' to send a request to User 'B' and then User 'B' either accepts or rejects it.I want it to be like the Instagram model not Facebook model.[User A sends follow request to User B.If User B accepts request then User A follows User B and User B is not following User A,to do so User B has to send a request to User A].
My files:
schema.rb
class CreateFollowJoinTable < ActiveRecord::Migration
def change
create_table 'follows' do |t|
t.integer 'following_id', :null => false
t.integer 'follower_id', :null => false
t.boolean :accepted, default: false
t.timestamps null: false
end
add_index :follows, :following_id
add_index :follows, :follower_id
add_index :follows, [:following_id, :follower_id], unique: true
end
end
app/models/follow.rb
class Follow < ActiveRecord::Base
belongs_to :follower, foreign_key: 'follower_id', class_name: 'User'
belongs_to :following, foreign_key: 'following_id', class_name: 'User'
end
app/models/user.rb
has_many :follower_relationships, foreign_key: :following_id, class_name: 'Follow'
has_many :followers, through: :follower_relationships, source: :follower
has_many :following_relationships, foreign_key: :follower_id, class_name: 'Follow'
has_many :following, through: :following_relationships, source: :following
def follow(user_id)
following_relationships.create(following_id: user_id)
end
def unfollow(user_id)
following_relationships.find_by(following_id: user_id).destroy
end
routes.rb
post ':user_name/follow_user', to: 'relationships#follow_user', as: :follow_user
post ':user_name/unfollow_user', to: 'relationships#unfollow_user', as: :unfollow_user
app/controllers/relationships_controller.rb
class RelationshipsController < ApplicationController
def follow_user
#user = User.find_by! user_name: params[:user_name]
if current_user.follow #user.id
respond_to do |format|
format.html { redirect_to root_path }
format.js
end
end
end
def unfollow_user
#user = User.find_by! user_name: params[:user_name]
if current_user.unfollow #user.id
respond_to do |format|
format.html { redirect_to root_path }
format.js
end
end
end
end
first you need to add status:boolean default:false to your following_relationships class
then you need to make a controller that notify the followed user about a new follower,
then you need make another controller for the followed user to edit the status from false to be true
like
def accept_follower
#relationships = current_user.following_relationships.find_by(follower_id: params[:follower_id])
#relationships.update_attributes(active: true)
end
def ignore_follower
current_user.following_relationships.find_by(follower_id: params[:follower_id]).destroy
end
then you need to fix your query about follower/following only select where status= true
has_many :followers, -> { where(status: true) } through: :follower_relationships, source: :follower
I'm trying to access all relations beetween two models: Serie has multiple categories and multiple categories can be in diferent series. Is a many to many relationship.
I try to do the following:
class SeriesController < ApplicationController
def category
#category = params[:category]
#series = []
Serie.all.each do |serie|
#serie.categories.all.each do |cat|
if #cat.category == #category
#series << #serie
end
end
end
end
end
Rails throws me that exception:
undefined method `categories' for nil:NilClass
Here are the models:
class Serie < ApplicationRecord
has_many :types
has_many :categories, through: :types
end
class Type < ApplicationRecord
belongs_to :serie
belongs_to :category
end
class Category < ApplicationRecord
has_many :types
has_many :series, through: :types
end
class CreateCategories < ActiveRecord::Migration[5.1]
def change
create_table :categories do |t|
t.string :category
t.timestamps
end
end
end
class CreateTypes < ActiveRecord::Migration[5.1]
def change
create_table :types do |t|
t.references :serie, index: true
t.references :category, index: true
t.timestamps
end
end
end
I don't know why this doesn't work.
Any idea? Thanks.
Change
Serie.all.each do |serie|
#serie.categories.all.each do |cat|
if #cat.category == #category
#series << #serie
end
# ...
to
Serie.all.each do |serie|
serie.categories.all.each do |cat|
if cat.category == #category
#series << serie
end
# ...
because there a local variables serie and cat defined in the blocks, but no instance variables #serie or #cat
You are mixing up your variables in your create method. You reference #serie which is set to equal [] so in the each it is empty, the variable you create there is serie so use that.
....
Serie.all.each do |serie|
serie.categories.all.each do |cat|
if cat.category == #category
#series << serie
end
end
end
In this Rails app, Users write Stories. Users can create Collections to group their Stories. However, they are allowed to publish Stories that don't belong to any Collection.
When creating a Story, I want the join table Story_Collections to save the Collection/Story ID pairs but it isn't working. Any help is appreciated! :)
Here's what I have
collection.rb
class Collection < ActiveRecord::Base
belongs_to :user
has_many :story_collections
has_many :stories, through: :story_collections
end
story.rb
class Story < ActiveRecord::Base
belongs_to :user
has_many :story_collections
has_many :collections, through: :story_collections
has_many :photos
end
story_collection.rb
class StoryCollection < ActiveRecord::Base
belongs_to :story
belongs_to :collection
end
In views/stories/new.html.erb
<%= f.select :collection_ids, Collection.all.pluck(:name, :id), {}, { multiple: true, class: "selectize" } %>
Creating the collections in collections_controller.rb
class CollectionsController < ApplicationController
def create
#collection = current_user.collections.build(collection_params)
if #collection.save
render json: #collection
else
render json: {errors: #collection.errors.full_messages}
end
end
private
def collection_params
params.require(:collection).permit(:name, :description)
end
end
Creating the stories
class StoriesController < ApplicationController
def new
#story = Story.new
authorize #story
end
def create
#story = current_user.stories.build(story_params)
authorize #story
end
private
def story_params
params.require(:story).permit(:title, :description, category_ids: [],
photos_attributes: [:id, :file_name, :file_name_cache, :_destroy])
end
end
The Story and Collection tables are saving correctly, only the join table is not. Here's the schema for the join table.
create_table "story_collections", force: :cascade do |t|
t.integer "story_id"
t.integer "collection_id"
t.datetime "created_at"
t.datetime "updated_at"
end
You are missing strong-params permitting the parameter story[collection_ids]
def story_params
params.require(:story).permit(
:title,
:description,
collection_ids: [], # you need to whitelist this, so the value gets set
category_ids: [],
photos_attributes: [
:id,
:file_name,
:file_name_cache,
:_destroy
]
)
end
So I have a couple of models in my app and they are all registered with ActiveAdmin. They all work great except for one and I can't figure out why. I keep getting the same error:
NameError at /admin/reports
uninitialized constant Report::Users
The model that it is happening on is called Report
class Report < ActiveRecord::Base
belongs_to :users
belongs_to :cars
enum reason: [:accident,:totaled,:stolen]
validates :reason, presence:true
end
The controller looks like this:
Class ReportsController < ApplicationController
before_action :authenticate_user!
def create
#car=Car.find(params[:car_id])
#report=#car.reports.build(report_params)
#report.user_id=current_user.id
#report.car_id=#car.id
if #report.save
redirect_to car_path(car)
else
render 'new'
end
end
def destroy
#report=Report.find(params[:id])
#report.destroy
end
private
def report_params
params.require(:report).permit(:reason)
end
end
This is the migration used to create the model:
class CreateReports < ActiveRecord::Migration
def change
create_table :reports do |t|
t.references :user, index: true
t.references :car, index: true
t.integer :reason, default: 0
t.timestamps null: false
end
add_foreign_key :reports, :users
add_foreign_key :reports, :cars
end
end
Lastly here is the active_admin app/admin/report.rb:
ActiveAdmin.register Report do
# See permitted parameters documentation:
# https://github.com/activeadmin/activeadmin/blob/master/docs/2-resource-customization.md#setting-up-strong-parameters
#
# permit_params :list, :of, :attributes, :on, :model
#
# or
#
# permit_params do
# permitted = [:permitted, :attributes]
# permitted << :other if resource.something?
# permitted
# end
end
I have been trying to figure it out for a couple of hours. Solutions that I saw on SO that don't work. I ran rails generate active_admin:resource Report to create it so it is singular. Why is it misbehaving?
NameError at /admin/reports uninitialized constant Report::Users
Association name for a belongs_to should be singular as per naming conventions.
class Report < ActiveRecord::Base
belongs_to :user #here
belongs_to :car #and here too
enum reason: [:accident,:totaled,:stolen]
validates :reason, presence:true
end
I've been searching for a while now, but google isn't really helping me.
The ArgumentError Unknown key(s): client_id appears in the ProjectsController:
# projects_controller.rb
class Management::ProjectsController < Management::ManagementController
def index
#projects = Project.find( :client_id => current_user.client )
end
end
This is the project model:
# project.rb
class Project < ActiveRecord::Base
belongs_to :client
end
This is the client model:
# client.rb
class Client < ActiveRecord::Base
has_many :projects
end
And finally, the migration:
# 20110404155917_create_projects.rb
class CreateProjects < ActiveRecord::Migration
def self.up
create_table :projects do |t|
t.string :name
t.datetime :date
t.text :description
t.integer :client_id
t.timestamps
end
end
def self.down
drop_table :projects
end
end
Should be possible, right?
Can't see what I'm missing here..
Anyone got a suggestion?
Thanks!
Use
#projects = Project.where( :client_id => current_user.client.id)
or
#projects = Project.find_by_client_id(current_user.client.id)
or you could do
#projects = current_user.client.projects
Little bit cleaner perhaps?