fragmentary 0.2.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -44,7 +44,7 @@ module Fragmentary
44
44
  end
45
45
 
46
46
  include ActiveSupport::Callbacks
47
- define_callbacks :after_destroy
47
+ define_callbacks :after_create, :after_destroy
48
48
 
49
49
  attr_reader :subscriber
50
50
  attr_accessor :record
@@ -55,7 +55,10 @@ module Fragmentary
55
55
  end
56
56
 
57
57
  def after_create(record)
58
- call_method(:"create_#{record.class.model_name.param_key}_successful", record)
58
+ run_callbacks :after_create do
59
+ @record = record
60
+ call_method(:"create_#{record.class.model_name.param_key}_successful", record)
61
+ end
59
62
  end
60
63
 
61
64
  def after_update(record)
@@ -1,38 +1,66 @@
1
1
  require 'rails/console/app'
2
+ require 'http'
3
+ require 'nokogiri'
2
4
 
3
5
  module Fragmentary
4
6
 
5
- class UserSession
7
+ class InternalUserSession
6
8
 
7
9
  include Rails::ConsoleMethods
8
10
 
9
- def initialize(user, &block)
11
+ def initialize(target, user=nil, &block)
10
12
  # app is from Rails::ConsoleMethods. It returns an object ActionDispatch::Integration::Session.new(Rails.application)
11
13
  # with some extensions. See https://github.com/rails/rails/blob/master/railties/lib/rails/console/app.rb
12
14
  # The session object has instance methods get, post etc.
13
15
  # See https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/testing/integration.rb
14
16
  @session = app
15
- sign_in if @credentials = session_credentials(user)
17
+ @user = user
18
+ @target = URI.parse(target)
19
+ @session.host! session_host
20
+ sign_in if session_credentials
16
21
  instance_eval(&block) if block_given?
17
22
  end
18
23
 
19
- def session_credentials(user)
20
- credentials = user.try(:credentials)
21
- credentials.is_a?(Proc) ? credentials.call : credentials
24
+ def session_host
25
+ @session_host ||= @target.host + ((port=@target.port) ? ":#{port}" : "")
22
26
  end
23
27
 
24
- def method_missing(method, *args)
25
- @session.send(method, *args)
28
+ def session_sign_in_path
29
+ @sign_in_path ||= Fragmentary.config.get_sign_in_path
26
30
  end
27
31
 
28
- def sign_out
29
- post Fragmentary.config.sign_out_path, {:_method => 'delete', :authenticity_token => request.session[:_csrf_token]}
32
+ def session_sign_out_path
33
+ @sign_out_path ||= Fragmentary.config.sign_out_path
34
+ end
35
+
36
+ def session_credentials
37
+ return nil unless @user
38
+ @credentials ||= begin
39
+ credentials = @user.credentials
40
+ credentials.is_a?(Proc) ? credentials.call : credentials
41
+ end
42
+ end
43
+
44
+ def relative_url_root
45
+ @relative_url_root ||= Rails.application.config.relative_url_root
46
+ end
47
+
48
+ def session_options
49
+ @session_options ||= relative_url_root ? {:env => {'SCRIPT_NAME' => relative_url_root}} : {}
50
+ end
51
+
52
+ def method_missing(method, *args)
53
+ @session.send(method, *args)
30
54
  end
31
55
 
32
56
  def sign_in
33
- get Fragmentary.config.get_sign_in_path # necessary in order to get the csrf token
57
+ raise "Can't sign in without user credentials" unless session_credentials
58
+ send_request(:method => :get, :path => session_sign_in_path, :options => session_options) # necessary in order to get the csrf token
34
59
  # NOTE: In Rails 5, params is changed to a named argument, i.e. :params => {...}. Will need to be changed.
35
- post Fragmentary.config.post_sign_in_path, @credentials.merge(:authenticity_token => request.session[:_csrf_token])
60
+ # Note that request is called on session, returning an ActionDispatch::Request; request.session is an ActionDispatch::Request::Session
61
+ puts " * Signing in as #{session_credentials.inspect}"
62
+ parameters = session_credentials.merge(:authenticity_token => request.session[:_csrf_token])
63
+ send_request(:method => :post, :path => session_sign_in_path, :parameters => parameters, :options => session_options)
36
64
  if @session.redirect?
37
65
  follow_redirect!
38
66
  else
@@ -40,39 +68,89 @@ module Fragmentary
40
68
  end
41
69
  end
42
70
 
43
- end
71
+ def follow_redirect!
72
+ raise "not a redirect! #{status} #{status_message}" unless redirect?
73
+ if (url = response.location) =~ %r{://}
74
+ destination = URI.parse(url)
75
+ path = destination.query ? "#{destination.path}?#{destination.query}" : destination.path
76
+ end
77
+ path = relative_url_root ? path.gsub(Regexp.new("^#{relative_url_root}"), "") : path
78
+ send_request(:method => :get, :path => path, :options => session_options)
79
+ status
80
+ end
44
81
 
45
- class SessionUser
82
+ def send_request(method:, path:, parameters: nil, options: {})
83
+ options.merge!({:params => parameters})
84
+ options.merge!(session_options)
85
+ if options.try(:[], :xhr)
86
+ puts " * Sending xhr request '#{method.to_s} #{path}'" + (!parameters.nil? ? " with #{parameters.inspect}" : "")
87
+ Rails.logger.info " * Sending xhr request '#{method.to_s} #{path}'" + (!parameters.nil? ? " with #{parameters.inspect}" : "")
88
+ else
89
+ puts " * Sending request '#{method.to_s} #{path}'" + (!parameters.nil? ? " with #{parameters.inspect}" : "")
90
+ Rails.logger.info " * Sending request '#{method.to_s} #{path}'" + (!parameters.nil? ? " with #{parameters.inspect}" : "")
91
+ end
92
+ @session.send(method, path, options)
93
+ end
46
94
 
47
- def self.all
48
- @@all ||= Hash.new
95
+ def sign_out
96
+ # request is called on session, returning an ActionDispatch::Request; request.session is an ActionDispatch::Request::Session
97
+ parameters = {:_method => 'delete', :authenticity_token => request.session[:_csrf_token]}
98
+ send_request(:method => :post, :path => session_sign_out_path, :parameters => parameters, :options => session_options)
49
99
  end
50
100
 
51
- def self.fetch(key)
52
- all[key]
101
+ end
102
+
103
+ class ExternalUserSession
104
+
105
+ def initialize(target, user=nil)
106
+ @target = URI.parse(target)
107
+ @relative_url_root = @target.path
108
+ @session = HTTP.persistent(target)
109
+ @cookie = nil
110
+ @authenticity_token = nil
111
+ sign_in if @credentials = session_credentials(user)
53
112
  end
54
113
 
55
- def initialize(user_type, options={})
56
- if user = self.class.fetch(user_type)
57
- if user.options != options
58
- raise RangeError, "You can't redefine an existing SessionUser object: #{user_type.inspect}"
59
- else
60
- user
61
- end
114
+ def send_request(method:, path:, parameters: nil, options: {})
115
+ if options.try(:[], :xhr)
116
+ Rails.logger.info " * Sending xhr request '#{method.to_s} #{path}'" + (!parameters.nil? ? " with #{parameters.inspect}" : "")
62
117
  else
63
- @user_type = user_type
64
- @options = options
65
- self.class.all.merge!({user_type => self})
118
+ Rails.logger.info " * Sending request '#{method.to_s} #{path}'" + (!parameters.nil? ? " with #{parameters.inspect}" : "")
66
119
  end
120
+ unless path =~ %r{://}
121
+ path = @relative_url_root + path
122
+ end
123
+ cookies = @cookie ? {@cookie.name.to_sym => @cookie.value} : {}
124
+ headers = options.try(:delete, :headers) || {}
125
+ headers.merge!({:'X-Requested-With' => 'XMLHttpRequest'}) if options.try(:delete, :xhr)
126
+ response = @session.cookies(cookies).headers(headers).send(method, path, {:json => parameters})
127
+ @cookie = response.cookies.first
128
+ @authenticity_token = Nokogiri::HTML.parse(response.to_s).css('head meta[name="csrf-token"]').first.try(:[], 'content')
129
+ if (response.code >=300) && (response.code <=399)
130
+ location = response.headers[:location]
131
+ options = {:headers => {:accept => "text/html,application/xhtml+xml,application/xml"}}
132
+ response = send_request(:method => :get, :path => location, :parameters => nil, :options => options)
133
+ end
134
+ response
67
135
  end
68
136
 
69
- def credentials
70
- options[:credentials]
137
+ def session_credentials(user)
138
+ credentials = user.try(:credentials)
139
+ credentials.is_a?(Proc) ? credentials.call : credentials
71
140
  end
72
141
 
73
- protected
74
- def options
75
- @options
142
+ def sign_in
143
+ # The first request retrieves the authentication token
144
+ response = send_request(:method => :get, :path => Fragmentary.config.get_sign_in_path)
145
+ puts " * Signing in as #{@credentials.inspect}"
146
+ response = send_request(:method => :post, :path => Fragmentary.config.post_sign_in_path,
147
+ :parameters => @credentials.merge(:authenticity_token => @authenticity_token),
148
+ :options => {:headers => {:accept => "text/html,application/xhtml+xml,application/xml"}})
149
+ end
150
+
151
+ def sign_out
152
+ send_request(:method => :delete, :path => Fragmentary.config.sign_out_path, :parameters => {:authenticity_token => @authenticity_token})
153
+ @session.close
76
154
  end
77
155
  end
78
156
 
@@ -1,3 +1,3 @@
1
1
  module Fragmentary
2
- VERSION = "0.2.2"
2
+ VERSION = "0.4.0"
3
3
  end
data/lib/fragmentary.rb CHANGED
@@ -7,9 +7,12 @@ require 'fragmentary/request'
7
7
  require 'fragmentary/fragment'
8
8
  require 'fragmentary/handler'
9
9
  require 'fragmentary/user_session'
10
+ require 'fragmentary/session_user'
10
11
  require 'fragmentary/widget_parser'
11
12
  require 'fragmentary/widget'
12
13
  require 'fragmentary/publisher'
14
+ require 'fragmentary/jobs/send_requests_job'
15
+ require 'fragmentary/jobs/dispatch_handlers_job'
13
16
 
14
17
  module Fragmentary
15
18
  def self.config
@@ -18,4 +21,12 @@ module Fragmentary
18
21
  @config
19
22
  end
20
23
  class << self; alias setup config; end
24
+
25
+ def self.application
26
+ Rails.application
27
+ end
28
+
29
+ def self.application_root_url
30
+ application.routes.url_helpers.root_url
31
+ end
21
32
  end
metadata CHANGED
@@ -1,63 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fragmentary
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Thomson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-07-02 00:00:00.000000000 Z
11
+ date: 2023-11-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: 4.0.0
20
- - - "<"
17
+ - - "~>"
21
18
  - !ruby/object:Gem::Version
22
- version: '5'
19
+ version: '6.0'
23
20
  type: :runtime
24
21
  prerelease: false
25
22
  version_requirements: !ruby/object:Gem::Requirement
26
23
  requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- version: 4.0.0
30
- - - "<"
24
+ - - "~>"
31
25
  - !ruby/object:Gem::Version
32
- version: '5'
26
+ version: '6.0'
33
27
  - !ruby/object:Gem::Dependency
34
- name: delayed_job_active_record
28
+ name: wisper-activerecord
35
29
  requirement: !ruby/object:Gem::Requirement
36
30
  requirements:
37
31
  - - "~>"
38
32
  - !ruby/object:Gem::Version
39
- version: '4.1'
33
+ version: '1.0'
40
34
  type: :runtime
41
35
  prerelease: false
42
36
  version_requirements: !ruby/object:Gem::Requirement
43
37
  requirements:
44
38
  - - "~>"
45
39
  - !ruby/object:Gem::Version
46
- version: '4.1'
40
+ version: '1.0'
47
41
  - !ruby/object:Gem::Dependency
48
- name: wisper-activerecord
42
+ name: http
49
43
  requirement: !ruby/object:Gem::Requirement
50
44
  requirements:
51
45
  - - "~>"
52
46
  - !ruby/object:Gem::Version
53
- version: '1.0'
47
+ version: 3.0.0
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
51
  requirements:
58
52
  - - "~>"
59
53
  - !ruby/object:Gem::Version
60
- version: '1.0'
54
+ version: 3.0.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: nokogiri
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
61
69
  - !ruby/object:Gem::Dependency
62
70
  name: bundler
63
71
  requirement: !ruby/object:Gem::Requirement
@@ -120,13 +128,17 @@ files:
120
128
  - fragmentary.gemspec
121
129
  - lib/fragmentary.rb
122
130
  - lib/fragmentary/config.rb
123
- - lib/fragmentary/dispatcher.rb
124
131
  - lib/fragmentary/fragment.rb
125
132
  - lib/fragmentary/fragments_helper.rb
126
133
  - lib/fragmentary/handler.rb
134
+ - lib/fragmentary/jobs/dispatch_handlers_job.rb
135
+ - lib/fragmentary/jobs/send_requests_job.rb
127
136
  - lib/fragmentary/publisher.rb
128
137
  - lib/fragmentary/request.rb
129
138
  - lib/fragmentary/request_queue.rb
139
+ - lib/fragmentary/serializers/handler_serializer.rb
140
+ - lib/fragmentary/serializers/request_queue_serializer.rb
141
+ - lib/fragmentary/session_user.rb
130
142
  - lib/fragmentary/subscriber.rb
131
143
  - lib/fragmentary/subscription.rb
132
144
  - lib/fragmentary/user_session.rb
@@ -152,8 +164,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
152
164
  - !ruby/object:Gem::Version
153
165
  version: '0'
154
166
  requirements: []
155
- rubyforge_project:
156
- rubygems_version: 2.4.8
167
+ rubygems_version: 3.0.9
157
168
  signing_key:
158
169
  specification_version: 4
159
170
  summary: Fragment modeling and caching for Rails