Apologies for the beginner question. I'm trying to use the Koala gem on my app. Currently, I have devise and omniauth (for facebook login). And they work great - I'm able to register users easily. What I want to do now though is utilize Koala to get access to Facebook data from my logged in Users. However, I'm getting an error "undefined method `oauth_token=' for #
User.rb
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable, omniauth_providers: [:facebook]
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
user.username = auth.info.name
user.avatar = URI.parse(auth.info.image)
user.oauth_token = auth.credentials.token #Added this after learning about Koala
end
end
def facebook
#facebook ||= Koala::Facebook::API.new(oauth_token)
end
end
Application_Controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
before_filter :set_body_class
before_filter :set_current_user
def set_current_user
User.current_user = current_user
end
def set_body_class
#body_class = "#{controller_name} #{action_name}"
end
protected
def after_sign_in_path_for(resource)
# request.env['omniauth.origin'] || stored_location_for(resource) || root_path
items_path
end
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:username, :name, :avatar])
devise_parameter_sanitizer.permit(:account_update, keys: [:username,:name, :avatar])
end
end
Schema.rb
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.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "avatar_file_name"
t.string "avatar_content_type"
t.integer "avatar_file_size"
t.datetime "avatar_updated_at"
t.string "username"
t.string "provider"
t.string "uid"
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
Migration AddOmniauthToUsers
class AddOmniauthToUsers < ActiveRecord::Migration[5.0]
def change
add_column :users, :provider, :string
add_column :users, :uid, :string
end
end
Try and call self.outh_token. outh_token belongs to a user and unless you pass a user as a parameter or call it on itself using "self", Rails doesn't know where outh_token belongs to.
def facebook
#facebook ||= Koala::Facebook::API.new(self.oauth_token)
end
or
def facebook(user)
#facebook ||= Koala::Facebook::API.new(user.oauth_token)
end
Related
I save the #booking with a user (called "booker"). Right after the #booking.save I can retrieve #booking.booker in the command line that display all the properties from the user (email, password, id, etc.). However After leaving the create method, impossible to retrieve it (for example from the show) : #booking.booker = nil .
I guess that commes from a mistake in my booking model : I have belongs_to and has_many_through. If the error comes from here, how to solve it without having to change all the db?
booking_controller.rb
class BookingsController < ApplicationController
before_action :set_booking, only: [:show, :edit, :update ]
before_action :set_booking_format, only: [:destroy ]
def index
end
def my_bookings
#bookings = BookingPolicy::Scope.new(current_user, Booking).scope.where(booker: current_user)
end
def show
authorize #booking
end
def new
#garden = Garden.find(params[:garden_id])
#booking = Booking.new
authorize #booking
end
def create
#garden = Garden.find params[:garden_id]
#booking = #garden.bookings.build(booker: current_user)
authorize #booking
if #booking.save
redirect_to garden_booking_path(#booking, current_user)
end
end
def update
end
private
def set_booking
#booking = Booking.find(params[:id])
end
def set_booking_format
#booking = Booking.find(params[:format])
end
def booking_params
params.require(:booking).permit(:garden_id, :booker_id, :date)
end
end
booking.rb
class Booking < ApplicationRecord
belongs_to :garden
belongs_to :booker, class_name: "User"
end
garden.rb
class Garden < ApplicationRecord
belongs_to :user
has_many :bookings, dependent: :destroy
end
user.rb
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :gardens
has_and_belongs_to_many :bookings
end
schema.rb
create_table "bookings", force: :cascade do |t|
t.date "date"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.bigint "garden_id"
t.integer "booker_id"
t.index ["garden_id"], name: "index_bookings_on_garden_id"
end
create_table "gardens", force: :cascade do |t|
t.string "title"
t.text "details"
t.integer "surface"
t.text "address"
t.bigint "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.text "availabilities"
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", null: false
t.datetime "updated_at", null: false
t.boolean "admin", default: false
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 "bookings", "gardens"
end
In your model, user.rb:
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :gardens
has_and_belongs_to_many :bookings
end
The :bookings association should be has_many. You aren't using a join table.
See: https://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association
The belongs_to part of the habtm association is looking for a foreign key, which doesn't exist. You can retrieve #booking.booker before moving to a different controller action because you aren't hitting the database at all, you're just retrieving the instance variables' association.
Can somebody help me with this error? I add profile controller by console without model. Database it's working fine. I am sure that i have lastname and firstname in seed.rb and i just did db:setup/migration.
Here's the show.html
.page-header
.h1
=link_to #user.firstname + " " + #user.lastname, edit_user_registration_path
Database:
create_table "users", force: true 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.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
t.string "firstname"
t.string "lastname"
t.string "username"
t.boolean "admin", default: false
user.rb
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 :reviews
has_many :products
validates_presence_of :firstname, :lastname
end
Profile controler:
class ProfileController < ApplicationController
def show
#user = User.find_by_username(params[:id])
if #user
#reviews=#user.reviews.order(:created_at).reverse_order.limit(5)
render action: :show
end
end
end
This part
#user = User.find_by_username(params[:id])
returns nil, because you pass id from params as a username to find_by_username finder. In can't find the username (string) which is id (integer).
It should be
#user = User.find(params[:id])
Take a look at docs on how finders work
If you are using find_by_username then you should pass params[:username] instead of params[:id] .
Also this part:
if #user
#reviews=#user.reviews.order(:created_at).reverse_order.limit(5)
render action: :show
end
even if the if statement is false, render action: :show will still be called - it's the default.
if you defined a method that said nothing:
def test
end
rails would call: render action: :name_of_method
You need to use a redirect and unless:
redirect_to users_url, notice: 'user not found' unless #user
Good luck!
I'm new to RoR, and I would like to develop an app, but I have an issue with the belongs_to association. I am using devise for the authentication of my users, and I have an object called timesheet, I followed several tutorials and read a lot of forums but unfortunately user_id remains null in my db, so I do not know where does the problem come from.
If you can tell how to fix it, any links that can helps me, that would be great.
Schema.rb:
ActiveRecord::Schema.define(version: 20150128160116) do
create_table "timesheets", force: true do |t|
t.date "date"
t.time "working_start_time"
t.time "working_end_time"
t.integer "breaks"
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "timesheets", ["user_id"], name: "index_timesheets_on_user_id"
create_table "users", force: true 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.integer "current_sign_in_ip"
t.integer "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
timesheets_controller.rb
class TimesheetsController < ApplicationController
layout 'application'
def show
#timesheet=Timesheet.find(params[:id])
end
def index
#timesheet = Timesheet.all
end
def new
#timesheet = Timesheet.new
end
def create
#timesheet = Timesheet.create(timesheet_params)
redirect_to new_timesheet_path
end
def edit
#timesheet=Timesheet.find(params[:id])
end
def update
#timesheet = Timesheet.find(params[:id])
#timesheet.update_attributes(timesheet_params)
redirect_to student_table_path
end
user.rb 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 :timesheets
end
Timesheet.rb model
class Timesheet < ActiveRecord::Base
belongs_to :user
validates :user_id, :presence => true
end
Thanks in advance.
It will stay null because you are not using it in the timesheetsController, your create action should be like this :
def create
#timesheet = current_user.timesheets.build(timesheet_params)
redirect_to new_timesheet_path
end
You have to use that build method to reference the current_user, so the timesheet will have the current_user in the user_id field.
My application main gems: rails 4.1.1, pg, acts_as_tenant, devise and activeadmin.
Application description: saas multi-tenant app with subdomains (not using postgresql schemas).
I have 2 models: Account and User with:
account belongs_to :owner a class_name for User
user belongs_to :account and also acts_as_tenant(:account)
Note: if using acts_as_tenant, I am not sure I need to declare belongs_to?
On public domain (www.myapp.dev) user can create a new account and choose own subdomain. This user has the status of ‘owner’ for this particular subdomain/account. After account creation, user is redirected to custom subdomain for sign in. Once signed in, owner can create/invite other users to join his account.
On account creation, owner_id is correctly saved to account record. In ActiveAdmin I can filter my accounts by owners.
The problem is the account_id is not saved in the user record. Also in ActiveAdmin, when I try to edit the users records to add the account, the data is not saved…
I am learning Rails so please be easy :)
My Account model :
class Account < ActiveRecord::Base
RESTRICTED_SUBDOMAINS = %w(www)
belongs_to :owner, class_name: 'User'
validates :owner, presence: true
validates :name, presence: true
validates :subdomain, presence: true,
uniqueness: { case_sensitive: false },
format: { with: /\A[\w\-]+\Z/i, message: 'contains invalid characters' },
exclusion: { in: RESTRICTED_SUBDOMAINS, message: 'restricted' }
accepts_nested_attributes_for :owner
before_validation :downcase_subdomain
def self.current_id=(id)
Thread.current[:account_id] = id
end
def self.current_id
Thread.current[:account_id]
end
private
def downcase_subdomain
self.subdomain = subdomain.try(:downcase)
end
end
My User model :
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
belongs_to :account
acts_as_tenant(:account)
validates :lastname, presence: true, allow_nil: false
validates :firstname, presence: true, allow_nil: false
validates :password, presence: true, allow_nil: false
validates :email, presence: true, allow_nil: false #uniqueness: true,
def to_s
"#{firstname} #{lastname} (#{email})"
end
end
Application Controller :
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_filter :authenticate_user! #, :set_mailer_host
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:accept_invitation).concat([:firstname])
end
private
def current_account
#current_account ||= Account.find_by(subdomain: request.subdomain)
end
helper_method :current_account
def after_sign_out_path_for(resource_or_scope)
new_user_session_path
end
def after_invite_path_for(resource)
users_path
end
end
Account controller :
class AccountsController < ApplicationController
skip_before_filter :authenticate_user!, only: [:new, :create]
def new
#account = Account.new
#account.build_owner
end
def create
#account = Account.new(account_params)
if #account.valid?
#account.save
redirect_to new_user_session_url(subdomain: #account.subdomain)
else
render action: 'new'
end
end
private
def account_params
params.require(:account).permit(:subdomain, :name, owner_attributes: [:lastname, :firstname, :email, :password, :password_confirmation, :account_id])
end
end
User controller :
class UsersController < ApplicationController
def index
#users = User.all
end
end
And my db schema :
ActiveRecord::Schema.define(version: 20140619202210) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "accounts", force: true do |t|
t.string "name"
t.string "subdomain"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "owner_id"
end
create_table "active_admin_comments", force: true do |t|
t.string "namespace"
t.text "body"
t.string "resource_id", null: false
t.string "resource_type", null: false
t.integer "author_id"
t.string "author_type"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "active_admin_comments", ["author_type", "author_id"], name: "index_active_admin_comments_on_author_type_and_author_id", using: :btree
add_index "active_admin_comments", ["namespace"], name: "index_active_admin_comments_on_namespace", using: :btree
add_index "active_admin_comments", ["resource_type", "resource_id"], name: "index_active_admin_comments_on_resource_type_and_resource_id", using: :btree
create_table "admin_users", force: true 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.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "admin_users", ["email"], name: "index_admin_users_on_email", unique: true, using: :btree
add_index "admin_users", ["reset_password_token"], name: "index_admin_users_on_reset_password_token", unique: true, using: :btree
create_table "users", force: true 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.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "account_id"
t.string "lastname"
t.string "firstname"
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
end
Try:
class Account < ActiveRecord::Base
has_one :account
...
class User < ActiveRecord::Base
acts_as_tenant(:account)
...
Without belongs_to for User model.
I used devise to create my users and I am trying to get the user_id to save in the events table when I create an event, I keep getting the error "cant find user without id". Not sure what the problem is any pointers would be greatly appreciated.
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
validates_presence_of :first_name
validates_presence_of :last_name
validates_presence_of :email
validates_presence_of :encrypted_password
validates_presence_of :sign_in_count
has_many :events
end
class Event < ActiveRecord::Base
validates_presence_of :name
validates_presence_of :description
belongs_to :user
has_many :reviews
end
class EventsController < ApplicationController
def index
#events = Event.all
end
def new
#event = Event.new
end
def create
#user = User.find(params[:user_id])
#event = #user.events.build(event_params)
end
def show
#event = Event.find(params[:id])
end
protected
def event_params
params.require(:event).permit(:name, :event_key, :location, :date, :event_url, :description, :time,
:event, :user_id)
end
end
Here is my schema
ActiveRecord::Schema.define(version: 20131226220750) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "events", force: true do |t|
t.string "name", null: false
t.string "location"
t.string "event_url"
t.string "description", null: false
t.integer "user_id"
t.datetime "time"
t.datetime "event_date"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "event_key", null: false
end
add_index "events", ["event_key"], name: "index_events_on_event_key", unique: true, using: :btree
create_table "reviews", force: true do |t|
t.string "feedback_comments"
t.integer "rating", null: false
t.integer "event_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "users", force: true 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.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
t.string "first_name", null: false
t.string "last_name", null: false
t.string "twitter_handle"
t.string "linked_in_url"
t.string "phone_number"
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
end
Have you looked at params[:user_id] to see if it is what you think it is? I'm pretty sure params[:user_id] will be nil.
Let us look at your params handling:
def event_params
params.require(:event).permit(:name, :event_key, :location, :date, :event_url, :description, :time, :event, :user_id)
end
The require method will look for params[:event] and return it if found. Then permit will look for :name, :event_key, ..., :user_id within params[:event]. So your :user_id is probably params[:event][:user_id] rather than params[:user_id]. The result is that you're saying:
#user = User.find(nil)
and find doesn't want to hear about nils.
This should work better:
def create
event = event_params
#user = User.find(event[:user_id])
#event = #user.events.build(event)
end
If #user is supposed to be the current user all the time then you'd want to get that out of current_user rather than params:
def create
#user = current_user
#event = #user.events.build(event_params)
end
#...
def event_params
params.require(:event).permit(:name, :event_key, :location, :date, :event_url, :description, :time, :event)
# No more :user_id up there
end