Giter VIP home page Giter VIP logo

Comments (5)

ernest4 avatar ernest4 commented on May 28, 2024 3

Yeah.. current_user is accessed pretty frequently though for any app with auth. In the controller you normally authenticate the user, then authorise the user to change some resource that only belongs to him/her.

With motion, this all happens in the motion callback now, so that's why I need current_user there to authorize the update.

I'm basically turning motion components into overpowered 'React like' things :D difference is that while React used to push / pull state to/from Redux (while synchronizing with backend via AJAX JSON) motion components simply, cleanly and directly just update the models in question - and i'm loving it :D

from motion.

alecdotninja avatar alecdotninja commented on May 28, 2024

Howdy, @ernest4 !

If I understand correctly, you do not need to un-comment that section in the initializer. You would only need to do that if you wanted to do something different than what is already there.

The session and cookies are available as instance methods (session and cookies respectively). If you are using Devise, current_user should be as well. The Rails Current object works separately from the session/cookies (it's a "thread-isolated attributes singleton").

If you want to use the user from there, you need to set it yourself. I suspect adding something like this to your component will give you what you want:

around_action :with_current_user

private

def with_current_user(&block)
  Current.set(user: current_user, &block)
end

from motion.

ernest4 avatar ernest4 commented on May 28, 2024

Sorry I'm still stuck :D

So I've commented out the motion config again.

And I'm trying to access the cookies and session in the component. This is the component:

module Account
  class LocalizationComponent < SvComponent
    include Motion::Component

    around_action :with_current_user

    def initialize
      @setting = Account::AccountComponent::ACCOUNT_SETTINGS.find do |setting|
        setting[:title] == 'Localization'
      end
    end

    map_motion :update_language

    def with_current_user(&block)
      debugger
      # Current.set(user: current_user, &block)
    end

    def update_language(event)
      # TODO: ...

      # Any of these puts will fail
      # puts current_user
      # puts session
      # puts cookies

      debugger
      # doest work, no cookies or session ... 
      # Current.user.update(:language => event.target.value)
    end

    def call
      div(:class => 'sv-container lg:w-2/3 mx-auto') do
        c div(:class => 'pt-4')
        c div(:class => 'sv-card w-full') {
          c span(t(@setting[:title]), :class => 'sv-text text-xl sv-text-bold')
          c div(:class => 'pt-2')
          c span(t(@setting[:subtitle]), :class => 'sv-text')
        }
        c div(:class => 'pt-4')
        c div(:class => 'sv-card') {
          c label(:user, :language, t('Language'), :class => 'sv-text')
          c div(:class => 'pt-2')
          c select(:user, :language, Localized::SUPPORTED_LANGUAGES.map { |lang| [lang, lang]},
                   { :selected => Current.user.language },
                   { :class => 'sv-input', :data => { :motion => 'update_language' } })
          # {:class => 'sv-input', :data => { :motion => 'change->update_language' }})
        }
      end
    end
  end
end

so at the two byebug points there im trying to access cookies or session but i get error?

Screenshot 2020-09-12 at 09 58 05

Screenshot 2020-09-12 at 10 04 50

still no sure what i'm doing wrong?

btw this is what my connection.rb looks like, does that mean that i should have access to current_user as well (because that errors out too)?

# frozen_string_literal: true

module ApplicationCable
  # handles incoming connection and authentication
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = find_verified_user_from_cookies
    end

    private

    # TODO: might need to stop using the reject_unauthorized_connection check here as this stops
    # socket traffic for non logged in users (when it might be desirable like in case of Motion
    # components).
    def find_verified_user_from_cookies
      current_user = User.find_by(:id => cookies.encrypted[:user_id])
      current_user #|| reject_unauthorized_connection
    end
  end
end

I tried calling @session, @cookies, @current_user but those all returned nil as well.

from motion.

ernest4 avatar ernest4 commented on May 28, 2024

Ok so i got it to work, but just wanna double check if this is the right conventional way to go about this.

So I can't access session or cookies in with_current_user or update_language, but those methods can access the instance variables of component. So i just set the instance variable for current_user in initialize, then use that in around_action hook, which then sets it up to be accessible in update_language callback (i could just access @current_user in update_language of course, but i think i'll just extract the around_action logic to SvComponent so i can have consistent access to Current.user, like the rest of the app.)

Does that all sound how it should be?

You've mentioned that 'The session and cookies are available as instance methods...' and i was looking at the motion code spec a little bit and they test that they are available in the render (i.e. the call method), which seems like they are available there. However I need to access them in the actual component class methods, so not sure if that actually works?

module Account
  class LocalizationComponent < SvComponent
    include Motion::Component

    around_action :with_current_user

    def initialize
      # ...

      # TODO: store id only and use that to look up in with_current_user
      # as marshaling objects is more memory intensive !!
      @current_user = Current.user
    end

    map_motion :update_language

    def with_current_user(&block)
      Current.set(:user => @current_user, &block)
    end

    def update_language(event)
      # TODO: error / success handling
      Current.user.update(:language => event.target.value)
    end

    def call
         # ...
    end

from motion.

alecdotninja avatar alecdotninja commented on May 28, 2024

So i just set the instance variable for current_user in initialize, then use that in around_action hook, which then sets it up to be accessible in update_language callback (i could just access @current_user in update_language of course, but i think i'll just extract the around_action logic to SvComponent so i can have consistent access to Current.user, like the rest of the app.)

👍 I don't see any issue with this approach. I think it is a good workaround until I figure something else out for the view context.

You've mentioned that 'The session and cookies are available as instance methods...' and i was looking at the motion code spec a little bit and they test that they are available in the render (i.e. the call method), which seems like they are available there. However I need to access them in the actual component class methods, so not sure if that actually works?

This is a really good point. I've yet to run across a situation where I wanted to use them outside of rendering, so I had not noticed. Unfortunately, with how ViewComponent works, this is not a simple fix. It happens because the current_user is being derived from the view context, and that is only available during render. 😞

from motion.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.