by

Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
    Larry Gebhardt
    @lgebhardt
    @guillaumebriday looks like a nice gem
    Adam Robertson
    @arcreative
    I’ve often wished JR was a bit more modular
    I’m very happy that so many of the internals are actually instance methods, as it’s allowed me to implement swaths of the functionality in different ways
    I mentioned this some time back, but I was looking for a way to take a certain query and output unpaginated CSV instead, which I have working perfectly now
    But I wish the interfaces were more modular so it didn’t feel so hacky
    Adam Robertson
    @arcreative
    I think another annoyance for my team is that for each resource, you need a controller, route entry, model, resource, policy, and processor, which means you need 6 test files as well. I feel like some things could be a bit more declarative to avoid duplication since some concerns don’t fit cleanly into one category or another
    Some of the tests can feel a bit tautological as well to the point where we’re considering not writing them in certain instances
    Adam Robertson
    @arcreative
    Not sure if anyone has used Vesa Lakso(sp)’s JSONAPI::Authorization gem, but there are some crossovers there as well, since not all auth concerns can be handled in pundit policies, namely for resource creation (I think this is more pundit’s fault though). Problematic use cases include records that are created by a user that need to have that user set as an owner—ideally we’d like them to be able to provide a user ID from the client (for admins, for instance), but also throw a 403 if that value doesn’t jive.
    Larry Gebhardt
    @lgebhardt
    @arcreative In my own project using JR I have some similar concerns. For example most of our controllers are empty classes (but share common code from a BaseController). I've wondered about implicitly creating the resource controllers, or possibly sending all routes a common controller.
    I think we could also create a catch all route function that would create default routes for all resources found in the system.
    While I believe both ideas could be implemented, I'm not sure they are a good ideas as they would make the system feel more opaque than it already does.
    I'd like to hear your thoughts on how we could restructure things to cut down the number of moving parts in a JR project.
    Adam Robertson
    @arcreative
    Sounds good! I’ll have some time playing around on a plane today, was thinking about toying around with some of these concepts. I think the controller is the one thing I’m okay retaining since we often have sub-routes that perform a more complex operation, but I feel like the model actually isn’t a bad place to determine the public representation of your resource, although some might argue that’s a more view-layer concern. Back in the day, I remember overriding to_json in the model was actually a common alternative to jbuilder or similar solutions.
    This is more of a gripe with rails than JR, but I also absolutely HATE having to look at schema.rb to see what my actual attributes are instead of being able to see them explicitly on the model along with everything else
    I feel like they should all be listed along with mutability and validators, instead of the opposite—so you would have models that use include JSONAPI::ActsAsResource much like your controller implements JSONAPI::ActsAsResourceController
    Adam Robertson
    @arcreative
    attribute :email, validates: [:presence, :valid_email, length: { maximum: 123 }], filterable: <true|custom_method>, etc.
    I've found a good practice in my case is to have logical rules around putting callbacks in either the resource or model, though, so this might be a conflict to combining the model and resource
    for instance, I want some created resources to generate an email, but I don't want the underlying model to do the same implicitly since we're often importing things in the backend that we don't want triggering those actions
    Karol Karwacki
    @karwank
    Hi @everyone, is it possible to define has_many relation which is always included ?
    I have a structure where menu has_many :menu-items and each menu-item has_many :menu-items, I don't want to define all possible levels in include parameter, I would rather preffer to include it automatically
    Karol Karwacki
    @karwank
    I have found a solution, for menu resource I have: has_many :menu_items, always_include_linkage_data: true and has_many :all_menu_items, class_name: 'MenuItem' and for menu-item I have has_many :menu_items, always_include_linkage_data: true, thanks of this all menu-items are added to included and data of each objects points to resource
    Karol Karwacki
    @karwank
    @lgebhardt you said: "The paginators add meta data like this. You can use one of the existing paginators, or create your own to customize the meta and the behavior", are you sure? I only see that response_document.rb does it and I'm not able to edit it.
    Larry Gebhardt
    @lgebhardt
    @karwank You are correct. I was wrong on that, sorry.
    Karol Karwacki
    @karwank
    do you know how I could achieve it ?
    I mean, how to modify top_level_meta, I know that I can rewrite base_meta method, but this metod is being fired before processor
    Larry Gebhardt
    @lgebhardt
    I'll look into it.
    Karol Karwacki
    @karwank
    Thank you !
    Larry Gebhardt
    @lgebhardt
    You will want to create a custom Processor. http://jsonapi-resources.com/v0.9/guide/operation_processors.html#Custom-OperatorProcessors. If you want this for all of your resource types you can set this class as the default in your config. Here's code for the Peeps demo application. This should be easily translated for your app.
    Config:
    JSONAPI.configure do |config|
    
      # :none, :offset, :paged, or a custom paginator name
      config.default_paginator = :paged
    
      # The default Operation Processor to use if one is not defined specifically
      # for a Resource.
      config.default_processor_klass = PeepsProcessor
    end
    Processor:
    class PeepsProcessor < JSONAPI::Processor
      after_find do
        unless @result.is_a?(JSONAPI::ErrorsOperationResult)
          @result.meta[:total_resources] = @result.record_count
          @result.meta[:resources_per_page] = @params[:paginator].size
          @result.meta[:page] = @params[:paginator].number
        end
      end
    end
    Karol Karwacki
    @karwank
    this is great !!
    Larry Gebhardt
    @lgebhardt
    You can also create resource specific processors if one default doesn't fit your needs
    Karol Karwacki
    @karwank
    one more question, how to avoid changing 'total_resources' to 'total-resources' ?
    Larry Gebhardt
    @lgebhardt
    The meta keys follow the same key formatting rules as the other keys in the response. You can do that globally in the config, but I'm assuming you want meta formatted differently than the resource?
    Karol Karwacki
    @karwank
    @lgebhardt yes, unfortunatelly my client library reads only total_resources and I can't change it
    @scottgonzalez thank you, I've seen it, I haven't found any example which shows it in action
    Larry Gebhardt
    @lgebhardt
    I don't see any good option, other than monkey patching the ResponseDocument. For v0.9 try this:
    module JSONAPI
      class ResponseDocument
        private
        def top_level_meta
          meta = @options.fetch(:base_meta, {})
    
          meta.merge!(@operation_results.meta)
    
          @operation_results.results.each do |result|
            meta.merge!(result.meta)
    
            if JSONAPI.configuration.top_level_meta_include_record_count && result.respond_to?(:record_count)
              meta[JSONAPI.configuration.top_level_meta_record_count_key] = result.record_count
            end
    
            if JSONAPI.configuration.top_level_meta_include_page_count && result.respond_to?(:page_count)
              meta[JSONAPI.configuration.top_level_meta_page_count_key] = result.page_count
            end
          end
    
          meta.as_json.deep_transform_keys { |key| UnderscoredKeyFormatter.format(key) }
        end
      end
    end
    Karol Karwacki
    @karwank
    ok, thank you, I always can do this:
    Larry Gebhardt
    @lgebhardt
    It will be different in v0.10 unforturnately
    Karol Karwacki
    @karwank
    class MyDasherizedKeyFormatter < JSONAPI::KeyFormatter
      class << self
        def format(_key)
          formatted = super.underscore
          unless ['total_resources', 'resources_per_page'].include? formatted
            formatted = formatted.dasherize
          end
          return formatted
        end
    
        def unformat(formatted_key)
          formatted_key.to_s.underscore
        end
      end
    end
    Larry Gebhardt
    @lgebhardt
    That will work, though it's a bit of an efficiency hit. Probably cleaner than a monkey patch in the long run
    Karol Karwacki
    @karwank
    as long as I know I will not use 'total_resources', 'resources_per_page' in other places
    Larry Gebhardt
    @lgebhardt
    yep
    Karol Karwacki
    @karwank
    Thank You for your help, now I have everything to go further
    Joe Gaudet
    @joegaudet
    On JR 9, if I have a relationship between two resources, and I wanted to apply some insert some custom eager loading of AR, where might I do that?
    Foo -> has_one -> Bar
    GET foos/1/bar
    If I wanted to do custom eager loading of the Bar relationship what might I override
    Note I am using caching
    Larry Gebhardt
    @lgebhardt
    @joegaudet There's a generated method record_for_bar that's created when you define the bar relationship on FooResource. It returns records so you could override self.record_for_bar and add your eager loading to a call to super.
    Thiago Felipe Peçanha
    @thiagopecanha

    Hello, first of all, thanks for the great jsonapi-resources gem
    I am trying to use the filter included feature, however even the searched text is not found, the included resource it’s listed.

    module Api
      module V1
        class HostnameResource < JSONAPI::Resource
          attributes :hosts
    
          has_many :domain_name_services
    
          filter :hosts, apply: lambda { |records, value, _options|
            records.where(' ? = ANY(hosts)', value)
          }
        end
      end
    end
    # frozen_string_literal: true
    
    module Api
      module V1
        class DomainNameServiceResource < JSONAPI::Resource
          attributes :ip
    
          has_many :hostnames
        end
      end
    end

    http://localhost:5000/api/v1/domain_name_services?include=hostnames&filter[hostnames.hosts]=123

    Could you help me to figure it out?