I am testing a ruby on rails app on localhost which needs authentication from dropbox.
When it says
App would like access to the files and folders in your Dropbox.
I click allow. Then I get
DropboxError in SessionsController#create
v1_retired
I have also,
session['access_token'] = access_token
#db = get_client access_token
name = #db.account_info['display_name']
email = #db.account_info['email']
uid = #db.account_info['uid']
user = User.find_by_provider_and_uid('dropbox', user_id) || User.create_with_omniauth(email, uid, name)
Where name = #db.account_info['display_name'] is in red mark is line 24.
file app/controllers/sessions_controller.rb:24:in `create'
Parameters:
{"state"=>"vJUckYTI8YJVzdw1L9OA8g==",
"code"=>"m6ncKLSfo7AAAAAAAAAADOJrqwYitp3Oi2HW8pXc",
"provider"=>"dropbox"}
sessions_controller.rb
require 'dropbox_sdk'
class SessionsController < ApplicationController
def get_auth
redirect_uri = ENV['db_callback']
flow = DropboxOAuth2Flow.new( ENV['db_key'], ENV['db_secret'], redirect_uri, session, :dropbox_auth_csrf_token)
end
def new
auth_url = get_auth.start
redirect_to auth_url
end
def index
if session['access_token'] != ''
#user = get_dropbox_client.account_info['display_name']
end
end
def create
code = params[:code]
begin
access_token, user_id, url_state = get_auth.finish(params)
rescue Exception
end
session['access_token'] = access_token
#db = get_client access_token
name = #db.account_info['display_name']
email = #db.account_info['email']
uid = #db.account_info['uid']
user = User.find_by_provider_and_uid('dropbox', user_id) || User.create_with_omniauth(email, uid, name)
session[:user_id] = uid
session[:access_token] = access_token
session[:user_name] = name
user.access_token = access_token
user.save
redirect_to '/'
end
def destroy
session.clear
redirect_to root_url
end
end
routs.rb
Rails.application.routes.draw do
match 'auth/:provider/callback', to: 'sessions#create', via: [:get, :post]
match '/', to: 'sites#load', constraints: { subdomain: /.+/ }, via: [:get, :post, :put, :patch, :delete]
root 'sites#index'
get '/logout', to: 'sessions#destroy'
get '/auth/dropbox', to: 'sessions#new'
match '/*req', to: 'sites#load', constraints: { subdomain: /.+/ }, via: [:get, :post, :put, :patch, :delete]
get '/about', to: 'pages#about'
get '/source', to: 'pages#source'
get '/pricing', to: 'pages#pricing'
get '/admin', to: 'pages#admin'
get '/webhook', to: 'webhook#challenge'
post '/webhook', to: 'webhook#post'
post "/versions/:id/revert", to: "versions#revert", as: "revert_version"
resources :sites, path: ''
end
I have gem 'dropbox-sdk' in my gemfile and application_controller.rb is
require 'dropbox_sdk'
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
def get_client at
return DropboxClient.new(at)
end
def current_user
User.find_by( access_token: session['access_token'] )
end
end
Gemfile
source 'https://rubygems.org'
gem 'figaro'
gem 'dropbox-sdk'
gem 'paper_trail'
gem 'httparty'
gem 'pry'
gem 'rails_12factor'
gem 'dalli'
group :development, :test do
gem 'rspec-rails', '~> 3.0'
end
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.2.8'
gem 'pg', '~> 0.20.0'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 4.0.3'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# Use CoffeeScript for .js.coffee assets and views
gem 'coffee-rails', '~> 4.0.0'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby
# Use jquery as the JavaScript library
gem 'jquery-rails'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', '~> 0.4.0', group: :doc
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring', group: :development
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'
# Use unicorn as the app server
# gem 'unicorn'
# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
# Use debugger
# gem 'debugger', group: [:development, :test]
How to change file application_controller.rb according to dropbox_api
because dropbox api V1 is already retired you need to upgrade your api
here follow this Dropbox API v1 → v2 Migration guide
and if you using gemfile to connect to the api,
the official dropbox api wrapper (dropbox-sdk-ruby) or gem 'dropbox-sdk'
is deprecated see their doc
you could use this 3rd party api wrapper instead dropbox_api
Related
I am trying to make a POST request to my Rails API that is uploaded to Heroku.
Currently I am testing with postman just to make sure it is working there before continuing to test between heroku apps.
Locally I am able to interact with my React frontend and my Rails API backend. No issues with localhost.
URL: https://appname.herokuapp.com/api/v1/users/
headers:
key: Access-Control-Allow-Origin, value: *
//I have also removed the access control allow origin so with and without.
key: Content-type, value: application/json
The data that is being passed in to create the user does get created, but the return response is 500 internal server error
[
{
"id": 1,
"first_name": "Roger",
"last_name": "Perez",
"email": "roger#yahoo.com",
"birthday": "2000-10-10",
"gender": "male",
"avatar": null,
"home_base": null,
"initials": null,
"comments": [],
"events": [],
"user_events": [],
"messages": []
},
Rails
class Api::V1::UsersController < ApplicationController
# before_action :requires_login, only: [:index]
# before_action :requires_user_match, only: [:show]
def index
#users = User.all
render json: #users
end
def create
puts "#{params}"
#user = User.new(get_params)
#verify_user = User.find_by(email: params[:email])
#user.email = params[:email]
#user.password = params[:password]
# if (#user.save)
if (#verify_user === nil && #user.save )
token = generate_token
render json: {
message: "You have been registed",
token: token,
id: #user.id,
status: :accepted
}
elsif (#verify_user.valid?)
render json: {
message: "You already have an account",
errors: #user.errors.full_messages,
verify: #verify_user,
status: :conflict}
else
render json: {
errors: #user.errors.full_messages,
status: :unprocessable_entity
}
end
end
private
def get_params
params.permit(:first_name, :last_name, :email, :password, :birthday, :gender,)
end
end
GEMFILE
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby '2.3.3'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.2.0'
# Use postgresql as the database for Active Record
gem 'pg', '>= 0.18', '< 2.0'
# Use Puma as the app server
gem 'puma', '~> 3.11'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
# gem 'jbuilder', '~> 2.5'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 4.0'
# Use ActiveModel has_secure_password
# Use ActiveStorage variant
# gem 'mini_magick', '~> 4.8'
# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
gem "rails_12factor", group: :production
gem 'jwt'
gem 'bcrypt', '~> 3.1.7'
gem 'rest-client', '~> 2.0', '>= 2.0.2'
# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.1.0', require: false
gem 'http'
# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
gem 'rack-cors'
gem 'active_model_serializers', '~> 0.10.0'
gem "dotenv-rails"
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end
group :development do
gem 'listen', '>= 3.0.5', '< 3.2'
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0'
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
LOG
2018-07-20T17:56:18.618067+00:00 heroku[router]: at=info method=POST path="/sessions" host=meetfriends-api.herokuapp.com request_id=e6471540-3038-46d8-ae68-3c671266ecd8 fwd="71.190.202.18" dyno=web.1 connect=0ms service=98ms status=500 bytes=203 protocol=https
cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins '*'
resource '*',
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end
Let me know if I am missing any details. Thanks for any help.
Since this is my first time uploading an app to Heroku I overlooked a simple mistake.
I needed to setup environment variables for the app to work since I was using JWT Auth and had secret keys in my .env file that do not get uploaded to my github.
https://devcenter.heroku.com/articles/config-vars
Once I configured env variables I was no longer getting the 500 internal server error.
From the docs:
View current config var values
heroku config
GITHUB_USERNAME: joesmith
OTHER_VAR: production
heroku config:get GITHUB_USERNAME
joesmith
Set a config var
heroku config:set GITHUB_USERNAME=joesmith
Adding config vars and restarting myapp... done, v12
GITHUB_USERNAME: joesmith
Remove a config var
heroku config:unset GITHUB_USERNAME
Unsetting GITHUB_USERNAME and restarting myapp... done, v13
You can also configure it through the dashboard.
I have run through mhartls's rails tutorial a few times with rails 4.x and just for fun, I started again, but updating to rails 5.0.0.beta1.
I have managed to find solution to all of the incompatibilities up to chapter 9. Specifically, I can't get the test of the destroy action on the users controller to work. I get:
ERROR["test_should_redirect_destroy_when_not_logged_in", UsersControllerTest, 1.489256506320089]
test_should_redirect_destroy_when_not_logged_in#UsersControllerTest (1.49s)
URI::InvalidURIError: URI::InvalidURIError: bad URI(is not URI?): http://www.example.com:80destroy
test/controllers/users_controller_test.rb:49:in `block (2 levels) in <class:UsersControllerTest>'
test/controllers/users_controller_test.rb:48:in `block in <class:UsersControllerTest>'
URI::InvalidURIError: bad URI(is not URI?): http://www.example.com:80destroy
test/controllers/users_controller_test.rb:49:in `block (2 levels) in <class:UsersControllerTest>'
test/controllers/users_controller_test.rb:48:in `block in <class:UsersControllerTest>'
bin/rails test test/controllers/users_controller_test.rb:47
my controller destroy action:
def destroy
User.find(params[:id]).destroy
flash[:success] = "User deleted"
redirect_to users_url
end
My test :
test "should redirect destroy when logged in as a non-admin" do
log_in_as(#other_user, integration_test: 'true')
assert_no_difference 'User.count' do
delete :destroy, params: { id: #user }
end
assert_redirected_to root_url
end
The links actually work, but test fails. I can get the test to pass by adding a route like this: delete 'delete_user' => 'users#destroy' AND changing the test to: delete delete_user_path params:{id: #user} however, the actual site and the test are using different routes, so I don't know if I can trust this. If I remove destroy from the users resources: resources :users, except: :destroy then the page link doesn't work but the test still passes. I don't see how to use the delete_user route on the page link and cant seem to get the user#destroy route to work in the test. I am aware that this is not an integration test, but this workaround fixed several other problems. I will refactor later, so that it makes sense.
Additional related controller code:
before_action :logged_in_user, only: [:index, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: :destroy
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
# Before filters
# Confirms a logged-in user.
def logged_in_user
unless logged_in?
store_location
flash[:danger] = "Please log in."
redirect_to login_url
end
end
# Confirms the correct user.
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless current_user?(#user)
end
# Confirms an admin user.
def admin_user
redirect_to(root_url) unless current_user.admin?
end
Test Helper Code:
# Logs in a test user. (I think all tests must be like integration)
def log_in_as(user, options = {})
password = options[:password] || 'password'
remember_me = options[:remember_me] || '1'
# the next line is the work around for rails version >=5.1
integration_test = options[:integration_test] || 'false'
if integration_test == 'true'
post login_path, params: { session: { email: user.email,
password: password,
remember_me: remember_me }
}
else
# params[:session][:user_id] = user.id
# session[:user_id] = user.id
controller.session[:user_id] = user.id
# params[session[:user_id] ] = user.id
end
end
Gemfile:
source 'https://rubygems.org'
ruby '2.3.0'
gem 'rails', '>= 5.0.0.beta1'
gem 'railties', '>= 5.0.0.beta1'
gem 'bcrypt', '>= 3.1.10'
gem 'faker', '>= 1.6.1'
gem 'carrierwave', '>= 0.10.0'
gem 'mini_magick', '>= 4.3.6'
gem 'fog', '>= 2.0.0.pre.0'
gem 'kaminari', :git => "git://github.com/amatsuda/kaminari.git", :branch => 'master'
gem 'kaminari-bootstrap', '>= 3.0.1'
gem 'bootstrap-sass', '>= 3.3.6'
gem 'sass-rails', '>= 5.0.4'
gem 'uglifier', '>= 2.7.2'
gem 'coffee-rails', '>= 4.1.1'
gem 'jquery-rails', '>= 4.0.5'
gem 'therubyracer', '>= 0.12.2'
gem 'turbolinks', github: 'rails/turbolinks'
gem 'jbuilder', '>= 2.4'
gem 'sdoc', '>= 0.4.1', group: :doc
gem 'net-ssh'
group :development, :test do
gem 'sqlite3', '>= 1.3.11'
gem 'byebug', '>= 8.2.1'
gem 'spring', '>= 1.6.1'
end
group :development do
gem 'web-console', '>= 3.0.0'
end
group :test do
gem 'minitest-reporters', '>= 1.1.7'
gem 'mini_backtrace', '>= 0.1.3'
gem 'guard', '>= 2.13.0'
gem 'guard-minitest', '>= 2.4.4'
gem 'minitest', '>= 5.8.3'
gem 'rails-controller-testing', '>= 0.0.3'
end
group :production do
gem 'pg', '>= 0.18.4'
gem 'rails_12factor', '>= 0.0.3'
gem 'puma', '>= 2.15.3'
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', '>= 1.2015.7', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
The correct solution is to replace:
delete :destroy, params: { id: #user }
with:
delete user_url(#user)
It seems that my in current setup ( see gemfile etc.) tokens ( :destroy , :user, etc) are not handled the same as in my previous setup (like mhartl recommends) so the fix I use is to replace all of the tokens in my tests with named routes (:user becomes user_path(#user). The destroy action doesn't seem to have a default named route so I added one to the routes.rb file.
I can get the test to pass by adding a route like this:
delete 'delete_user' => 'users#destroy'
AND changing the test to:
delete delete_user_path params:{id: #user}
however, the actual site and the test are using different routes to the same action, so I don't know if I can trust this as a final solution.
If i remove destroy from the users resources:
resources :users, except: :destroy
then the page link doesn't work but the test still passes. I don't see how to use the added 'delete_user(#user) route' on the page link, I keep getting user not found when I try, and I cant seem to get the user#destroy action to work in the test without the added route.
Error image
argument error
home_controller.rb
class HomeController < ApplicationController
def home
#activities = Activity.order("created_at DESC").page(params[:page]).per_page(5)
end
def login
render
end
def logout
session[:school_id] = nil
session[:parent_id] = nil
session[:user_id] = nil
redirect_to :controller => 'home', :action => 'login'
end
Gemfile
source 'https://rubygems.org'
gem 'rails', '4.2.4'
gem 'mysql2', '~> 0.3.20'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.1.0'
gem 'remotipart', '~> 1.2'
gem 'jquery-rails'
gem 'turbolinks'
gem 'jbuilder', '~> 2.0'
gem 'sdoc', '~> 0.4.0', group: :doc
gem 'bootstrap-sass', '~> 3.3.5'
gem 'sass-rails', '~> 5.0'
gem 'bootstrap_form'
gem 'devise', '~> 3.5', '>= 3.5.2'
gem 'bartt-ssl_requirement', '~>1.4.0', :require => 'ssl_requirement'
gem 'will_paginate'
gem 'paperclip'
gem 'bcrypt', '~> 3.1.7'
group :development, :test do
console
gem 'byebug'
end
redirect_to :controller => 'home', :action => 'login'
This is not correct, not to mention ugly. Instead, create a route in routes.rb that does that action. For example:
get 'login' => 'home#login'
Then you would use:
redirect_to login_path
BONUS
****You should read up on rails routing to make better routes too.****
Also, a home controller that handles logins does not seem very clean.
A better route would be something like the following but it requires different controller setup:
resources :sessions
which creates the following route and many others(not exactly but lets ignore the details):
get 'login' => 'sessions#new'
Again, I recommend you read up on Rails routing.
Just to explain the redirect_to actually expects a path not controller or action and Helsing has answered it very beautifully that how can you make a route out of controller and its action.
It looks to me that you may have had your code written incorrectly initially, and even though you've fixed the source code, Rails is still using the old (incorrect) version.
You must have had some variant of:
redirect_to 'home', :action => 'login'
redirect_to 'home', 'login'
before.
Leave your code the way you have it (redirect_to(:controller => 'home', :action => 'login')), and make sure you restart your Rails process correctly.
Hi I am learning how to use omniauth as backend for ember app.
when i run my application I get the below mentioned erroe
OmniAuth::NoSessionError - You must provide a session to use OmniAuth
on resue rails s my applicataion halts at line below.
172: def call!(env) # rubocop:disable CyclomaticComplexity
173: unless env['rack.session']
174: error = OmniAuth::NoSessionError.new('You must provide a session to use OmniAuth.')
=> 175: fail(error)
176: end
177:
config/intializer/devise
Devise.setup do |config|
config.mailer_sender = 'please-change-me-at-config-initializers-devise#example.com'
require 'devise/orm/active_record'
config.case_insensitive_keys = [ :email ]
config.strip_whitespace_keys = [ :email ]
config.http_authenticatable = true
config.skip_session_storage = [:http_auth]
config.stretches = Rails.env.test? ? 1 : 10
config.reconfirmable = true
config.expire_all_remember_me_on_sign_out = true
config.password_length = 8..128
config.reset_password_within = 6.hours
config.http_authenticatable_on_xhr = false
config.navigational_formats = ['*/*', :html,:json]
config.sign_out_via = :delete
require 'omniauth-facebook'
config.omniauth :facebook, ENV['8987087080'] , ENV['3d6a359a37c8780870dxxxx5'],:strategy_class => OmniAuth::Strategies::Facebook
end
config/intializer/session_store.rb
Rails.application.config.session_store :disabled
routes.rb
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
resources :users
resources :games
end
end
ActiveAdmin.routes(self)
#devise_for :admin_users, ActiveAdmin::Devise.config
devise_for :users, controllers: {
omniauth_callbacks: 'omniauth_callbacks',
sessions: 'sessions' ,
registrations: "registrations",
}
devise_scope :user do
match 'users/sign_in', to: 'sessions#create', via: :post
match 'api/v1/users' , to: 'registrations#create' , via: :post
end
end
gemfile.rb
source 'https://rubygems.org'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.1.6'
platforms :ruby do # linux
gem 'unicorn'
gem 'foreman'
gem 'delayed_job_active_record'
end
group :development, :test do
gem 'compass'
gem 'pry'
gem 'pry-remote'
gem 'pry-rails'
gem 'pry-rescue'
gem 'pry-stack_explorer'
gem 'pry-byebug'
gem 'guard'
gem 'guard-livereload'
gem 'guard-rails'
gem 'guard-rspec'
gem 'guard-cucumber'
gem 'guard-zeus'
gem 'rspec-rails'
end
group :production do
#gem 'pg'
end
#authentication
gem 'cancan'
gem 'rolify'
gem 'devise'
gem 'omniauth'
gem 'omniauth-facebook', '=1.4.0'
gem 'oauth2'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 4.0.0'
gem 'bootstrap-sass', '~> 3.1.1'
gem 'bootswatch-rails'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby
# Use jquery as the JavaScript library
gem 'jquery-rails'
group :doc do
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', require: false
end
#ember
gem "active_model_serializers"
gem "ember-source", "~>1.7.0"
#asyc http calls
gem 'hashie_rails'
gem "typhoeus"
gem "virtus"
#middleware
gem "rack-cors", require: 'rack/cors'
platforms :mswin do
gem "wdm", :group => [:development, :test]
end
#gem 'wdm', '>= 0.1.0'
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin]
It is because you disabled the session middleware (look at the output of rake middleware). Omniauth will not work without the session middleware.
You disabled it here: Rails.application.config.session_store :disabled
If you are trying to ditch session because you do not use it other than for Omniauth, then the only thing you can do is write your own middleware that injects ActionDispatch::Session::CookieStore and possibly other necessary middlewares based on the URL (i.e. if the URL is /auth/*). Here is an example of what I use to achieve this (only uses session if URL path is not /api/...):
# /config/application.rb
config.middleware.insert_before ActionDispatch::ParamsParser, "SelectiveStack"
# /config/initializers/omniauth.rb
::OmniAuthConfig = Proc.new do
provider :github, # ...
end
# /app/middleware/selective_stack.rb
class SelectiveStack
def initialize(app)
#app = app
end
def call(env)
if env["PATH_INFO"].start_with?("/api/") # <--- Change URL path here
#app.call(env)
else
middleware_stack.build(#app).call(env)
end
end
private
def middleware_stack
#middleware_stack ||= begin
ActionDispatch::MiddlewareStack.new.tap do |middleware|
# needed for OmniAuth
middleware.use ActionDispatch::Cookies
middleware.use Rails.application.config.session_store, Rails.application.config.session_options
middleware.use OmniAuth::Builder, &OmniAuthConfig
# needed for Doorkeeper /oauth views
middleware.use ActionDispatch::Flash
end
end
end
end
In this example I only enable the session middleware when the URL does not start with /api/. You will still need to remove Rails.application.config.session_store :disabled and properly set up your session store, of course. In my example I use the cookie store. You might need to tweak my example based on which middleware you are missing in rake middleware. But if you're not doing this for performance reasons then just reenable the session middleware.
Into application.rb
...
config.api_only = true
config.session_store :cookie_store, key: '_interslice_session'
config.middleware.use ActionDispatch::Cookies # Required for all session management
config.middleware.use ActionDispatch::Session::CookieStore, config.session_options
I have a bookmarks resource and have mapped it to serve json by default under my api namespace like so in my routes.rb:
namespace :api, defaults: {format: 'json'} do
resources :bookmarks
get ':username', to: 'users#index'
get ':username/bookmarks/:id', to: 'users#show'
end
I have a Api::UsersController controller and a supporting BookmarkSerializer that works just fine on an individual bookmark resource like http://localhost:3000/api/emma_carter/bookmarks/87
But when I try to hit http://localhost:3000/api/emma_carter which is supposed to serve all bookmarks owned by the user, I get all different kinds of errors. Here is my Api::UsersController
module Api
class UsersController < ApplicationController
respond_to :json
def index
user = User.find_by(username: params[:username])
bookmarks = user.bookmarks
render json: bookmarks
end
def show
user = User.find_by(username: params[:username])
bookmark = user.bookmarks.find_by(params[:id])
render json: bookmark
end
end
end
The show method works but the index method gives me ArgumentError in Api::UsersController#index
wrong number of arguments (1 for 0)
UPDATE: Full stack trace here: https://gist.github.com/amite/b79fc42bfd73de5a07bd
screenshot
Here is the serializer:
class BookmarkSerializer < ActiveModel::Serializer
attributes :id, :url, :title, :domain, :notes, :image, :created, :username
belongs_to :user
def created
object.created_at
end
def username
user.username
end
end
Looking at other solutions on stack overflow, I have also tried other versions of my index method:
def index
user = User.find_by(username: params[:username])
bookmarks = user.bookmarks
bookmarks.map { |bookmark| ::BookmarkSerializer.new(bookmark)}.to_json #updated line
end
This gives me the error:
Missing template api/users/index, application/index with {:locale=>[:en], :formats=>[:json], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]}.
Next the last version of my index method looks like this:
def index
user = User.find_by(username: params[:username])
bookmarks = user.bookmarks
ActiveModel::ArraySerializer.new(bookmarks, each_serializer: ::BookmarkSerializer).to_json
end
This gives me the error uninitialized constant ActiveModel::ArraySerializer
What am I doing wrong? I am using rails 4.1.5 and the github version of the active_model_serializers
gem.
gem 'active_model_serializers', github: 'rails-api/active_model_serializers'
UPDATE: Since I am trying to output a collection of bookmarks I also tried using a separate serializer
BookmarksSerializer but I am getting the same error: ArgumentError in Api::UsersController#index
wrong number of arguments (1 for 0)
UPDATE2: Here is a version of the index method that kinda works in the sense that it renders the resource collection in json format:
def index
user = User.find_by(username: params[:username])
bookmarks = user.bookmarks
respond_with bookmarks.to_json
end
But this still does not use the BookmarksSerializer
class BookmarksSerializer < ActiveModel::Serializer
attributes :id, :title
end
It just outputs the default hash
Full Gemfile
source 'https://rubygems.org'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.1.5'
# Use mysql as the database for Active Record
gem 'mysql2'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 4.0.3'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# Use CoffeeScript for .js.coffee assets and views
gem 'coffee-rails', '~> 4.0.0'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby
gem 'bourbon'
gem 'neat'
gem 'bitters'
gem 'refills'
gem 'wisper'
gem 'rails-ioc'
gem 'reform'
gem 'cells'
gem "pundit"
gem 'active_model_serializers', github: 'rails-api/active_model_serializers'
gem "font-awesome-rails"
gem 'simple_form'
# Use jquery as the JavaScript library
gem 'jquery-rails'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', '~> 0.4.0', group: :doc
group :development, :test do
# Call 'debugger' anywhere in the code to stop execution and get a debugger console
gem 'byebug'
gem 'ffaker'
gem 'pry-rails'
gem 'capybara'
gem 'factory_girl_rails'
gem 'database_cleaner'
gem 'capybara-webkit'
gem 'rspec-cells'
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
gem 'spring-commands-rspec'
gem 'rspec-rails'
gem 'guard-rspec'
gem 'rb-fsevent' if `uname` =~ /Darwin/
end
# Use ActiveModel has_secure_password
gem 'bcrypt', '~> 3.1.7'
# Use unicorn as the app server
# gem 'unicorn'
# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
# Use debugger
# gem 'debugger', group: [:development, :test]
turns out I need to include v0.9 of the gem
gem 'active_model_serializers', github: 'rails-api/active_model_serializers', branch: '0-9-stable'
you could try change:
def index
user = User.find_by(username: params[:username])
bookmarks = user.bookmarks
bookmarks.map { |bookmark| ::BookmarkSerializer.new(bookmark)}.to_json #updated line
end
to:
def index
user = User.find_by(username: params[:username])
bookmarks = user.bookmarks
render json: bookmarks.map { |bookmark| ::BookmarkSerializer.new(bookmark)}
end