in the following code I am running into an error which states syntax error, unexpected '\n', expecting :: or '[' or '.' (SyntaxError) But I don't see where the issue is.
module Xaaron
class ApiKey.class_eval # It does not like this....
include Promiscuous::Publisher
publish :xaaron_users_id, :api_key, :as => :ApiKey
end
end
Am I using class_eval wrong?
You can either remove the class keyword, and add do after calling class_eval (passing it a block):
module Xaaron
ApiKey.class_eval do
include Promiscuous::Publisher
publish :xaaron_users_id, :api_key, :as => :ApiKey
end
end
(given that ApiKey already exists)
OR you can remove the class_eval altogether:
module Xaaron
class ApiKey
include Promiscuous::Publisher
publish :xaaron_users_id, :api_key, :as => :ApiKey
end
end
This will work even if the ApiKey already exists... that's just the way ruby works...
Related
I am following this article to learn about writing api using grape gem. But in the response I am not getting the root key. Here is my directory structure,
app
|––controllers
|––api
|––base.rb
|––v1
|––base.rb
|––graduates.rb
In app/controllers/api/v1/graduates.rb:
module API
module V1
class Graduates < Grape::API
include API::V1::Defaults
resource :graduates do
desc "Return all graduates"
get "", root: :graduates do
Graduate.all
end
desc "Return a graduate"
params do
requires :id, type: String, desc: "ID of the
graduate"
end
get ":id", root: "graduate" do
Graduate.where(id: permitted_params[:id]).first!
end
end
end
end
end
in app/controllers/api/v1/defaults.rb
module API
module V1
module Defaults
extend ActiveSupport::Concern
included do
prefix "api"
version "v1", using: :path
default_format :json
format :json
formatter :json,
Grape::Formatter::ActiveModelSerializers
helpers do
def permitted_params
#permitted_params ||= declared(params,
include_missing: false)
end
def logger
Rails.logger
end
end
rescue_from ActiveRecord::RecordNotFound do |e|
error_response(message: e.message, status: 404)
end
rescue_from ActiveRecord::RecordInvalid do |e|
error_response(message: e.message, status: 422)
end
end
end
end
end
I have used grape-active_model_serializers gem to serialize like the following,
In app/serializers/graduate_serializer.rb
class GraduateSerializer < ActiveModel::Serializer
attributes :id, :name
end
I got the following output. [{"id":1,"name":"aaaa"},{"id":2,"name":"bbbb"},{"id":3,"name":"cccc"},{"id":4,"name":"dddd"}]
But As I added get "", root: :graduates do in app/controllers/api/v1/graduates.rb file, I am expecting the following output,
{"graduates": [{"id":1,"name":"aaaa"},{"id":2,"name":"bbbb"},{"id":3,"name":"cccc"},{"id":4,"name":"dddd"}]}
What I am missing. why graduates is not added as root. Help me to fix this issue.
Dirty fix: use in app/controllers/api/v1/graduates.rb
get "" do
{ graduates: Graduate.all }
end
Or you can delete gem grape-active_model_serializers, delete class GraduateSerializer, delete row formatter :json, Grape::Formatter::ActiveModelSerializers from defaults.rb, and add gem grape-entity to Gemfile, install it, add code to app/app/entities/graduate_entity.rb:
class GraduateEntity < Grape::Entity
root 'graduates', 'graduate'
expose :id
expose :name
end
Change code in app/app/controllers/api/v1/graduates.rb:
get "" do
present Graduate.all, with: GraduateEntity
end
I was struggling with similar issue as you, I resolved it by adding
ActiveModelSerializers.config.adapter = :json
in config/initializers/serializer.rb
Let me know if it could help you
Why does the Test.foo work, but Test2.foo? fail.
It seems it works without the '?', but I would prefer to have the ? to follow conversation that it's a boolean.
syntax error, unexpected tOP_ASGN
Works:
class Test
def foo
#foo ||= true # => true
end # => :foo
end # => :foo
FAILS:
class Test2
def foo?
#foo? ||= true # => true
end # => :foo
end # => :foo
? symbol is allowed at the end of a method name but #foo is an instance variable, not a method. And ? is not allowed in variables names
We're trying to set up rails routes with the parameters separated by more then just forward-slash symbols.
As an example:
someexample.com/SOME-ITEM-for-sale/SOME-PLACE
For the following path we'd like to extract SOME-ITEM and SOME-PLACE strings as parameters whilst identifying which controller to run it all against with the "-for-sale/" part.
I've been playing with variations on :constraints => {:item => /[^\/]+/} constructs but without any success. Am I looking in the right place? Thanks!
UPDATE
In the end I went with this solution:
get ':type/*place' => 'places#index', as: :place , :constraints => {:type => /[^\/]+-for-sale/}
And then recovered the full "SOME-ITEM-for-sale" sting for parsing in the controller using
params[:type]
Hope that helps someone!
friendly_id is what you want:
#Gemfile
gem 'friendly_id', '~> 5.1.0'
$ rails generate friendly_id
$ rails generate scaffold item name:string slug:string:uniq
$ rake db:migrate
#app/models/item.rb
class Item < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: [:slugged, :finders]
end
The above will give you a slug column, which FriendlyId will look up any requests you send to the app:
#config/routes.rb
resources :items, path: "" do
resources :places, path: "" #-> url.com/:item_id/:id
end
Although the params will still be id (unless you use the param option of resources, but FriendlyId will override both your routes and model to use the slug instead:
<%= link_to "Item Place", items_place_path(#item, #place) %> #-> url.com/item-name-information/place-name-information
Update
If you wanted to have a "dynamic" routing structure, you'll be able to use the following (this requires the history module of FriendlyId):
#config/routes.rb
#...
get '/:item_id/:place_id', to: SlugDispatcher.new(self), as: :item #-> this has to go at the bottom
#lib/slug_dispatcher.rb
class SlugDispatcher
#http://blog.arkency.com/2014/01/short-urls-for-every-route-in-your-rails-app/
##########################################
#Init
def initialize(router)
#router = router
end
#Env
def call(env)
id = env["action_dispatch.request.path_parameters"][:item_id]
slug = Slug.find_by slug: id
if slug
strategy(slug).call(#router, env)
else
raise ActiveRecord::RecordNotFound
end
end
##########################################
private
#Strategy
def strategy(url)
Render.new(url)
end
####################
#Render
class Render
def initialize(url)
#url = url
end
def call(router, env)
item = #url.sluggable_type.constantize.find #url.sluggable_id
controller = (#url.sluggable_type.downcase.pluralize + "_controller").classify.constantize
action = "show"
controller.action(action).call(env)
end
end
####################
end
This won't work out the box (we haven't adapted it for nested routes yet), but will provide you the ability to route to the appropriate controllers.
In the end we went with this solution:
get ':type/*place' => 'places#index', as: :place , :constraints => {:type => /[^\/]+-for-sale/}
The router command only gets activated if the :type parameter contains "-for-sale" in the string
And then we recovered the full "SOME-ITEM-for-sale" sting for parsing in the controller using
params[:type]
Hope that helps someone!
My objective is to dynamically load a set of methods to an ActiveRecord model instance based on an attribute that's set:
class Book < ActiveRecord::Base
after_initialize do |cp|
self.class.include "#{cp.subject}".constantize
end
end
I then have the following concerns:
module Ruby
extend ActiveSupport::Concern
def get_framework
'rails'
end
end
module Python
extend ActiveSupport::Concern
def get_framework
'django'
end
end
Then, when I run these separately, I get the correct framework string:
python_book = Book.create(:subject => 'python', :id => 1)
python_book.get_framework -> 'django'
ruby_book = Book.create(:subject => 'ruby', :id => 2)
ruby_book.get_framework -> 'rails'
My problem is that when I have both of the books returned in a query, the Concern is included is the last in the result set and is not picking up the correct Concern methods.
Books.all.order(:id => 'asc').collect do |book|
puts book.get_framework
end
# Result
['rails', 'rails']
I am assuming that this is because the 'include' is happening at the class level and not the instance level. Would love some help as to how to clean this up and make this work.
Use .extend
to add instance methods to a instances of Book instead.
Extends in action:
module Greeter
def say_hello
"Hello"
end
end
irb(main):008:0> a = Object.new
=> #<Object:0x00000101e01c38>
irb(main):009:0> a.extend(Greeter)
=> #<Object:0x00000101e01c38>
irb(main):010:0> a.say_hello
=> "Hello"
irb(main):011:0> Object.new.say_hello
NoMethodError: undefined method `say_hello' for #<Object:0x00000101e196d0>
class Book < ActiveRecord::Base
after_initialize do |cp|
self.extend subject.constantize
end
end
I'm writing a ruby-on-rails library module:
module Facets
class Facet
attr_accessor :name, :display_name, :category, :group, :special
...
URI = {:controller => 'wiki', :action => 'plants'}
SEARCH = {:status => WikiLink::CURRENT}
#Parameters is an hash of {:field => "1"} values
def render_for_search(parameters)
result = link_to(display_name, URI.merge(parameters).merge({name => "1"}))
count = WikiPlant.count(:conditions => (SEARCH.merge(parameters.merge({name => "1"}))))
result << "(#{count})"
end
end
...
end
when I call render_for_search I get the error
undefined method 'link_to'
I've tried requiring url_helper directly but can't figure out what's going wrong.
Try this:
ActionController::Base.helpers.link_to
This is because, ActionView urlhelpers are only available to the Views, not in your lib directory.
the link_to method is found in the ActionView::Helpers::UrlHelper module, plus you wou
so try this.
class Facet
include ActionView::Helpers::UrlHelper
...
end
Simply including the helper doesn't get you much further. The helpers assume that they are in the context of a request, so that they can read out the domain name and so on.
Do it the other way around; include your modules in the application helper, or something like that.
# lib/my_custom_helper.rb
module MyCustomHelper
def do_stuff
# use link_to and so on
end
end
# app/helpers/application_helper.rb
module ApplicationHelper
include MyCustomHelper
end