pundit_can 0.1.3 → 0.1.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 68cee5b5723a2c0b9640e59280996fc46df7d91b3def9b26a586e13350e94788
4
- data.tar.gz: 543cb75c45f2ff523c80a1339a9e474a61b65610206fa68ff5c4da5a365d2268
3
+ metadata.gz: 95df5ff56989946351acaa622d23e1aa0d0575e8cce7c47dd4e47b266a02c247
4
+ data.tar.gz: e9f75be20b4e055f0583657ef05d3dcea4cdb314f6998642bef734c369fd8024
5
5
  SHA512:
6
- metadata.gz: ac50a363d20811f5853520cebb4ab6e16cb1d0b59c91e8d81df311df97fafb36e72116c27343e723210f6024254c257ba6082744eeaa4df00f18ce893bd4a7fd
7
- data.tar.gz: d6898b262559d7cd73215b8227de81e387d73257525bcde96611847c821223f54a173fcd0c016dfe4dedfdae8d503afc1b148b387c7dd13a5475e7db8244969f
6
+ metadata.gz: 1ff5fb33b343efd582132d77edeb12651b73dd40f0c035c301997beb6f775cdd3a9dbfb660f16897f0a0f34655beeddab96d32f48732497229dd03900cdeafc6
7
+ data.tar.gz: 365fbe976dea92ef37d57701f363f6f416a078983e46bd9a6002cdb9283a1341df0ca5c163c7b5de95f2861b483a2e17cc086ba1518d5a6d365ac523cdbdccbd
data/README.md CHANGED
@@ -44,6 +44,35 @@ And it will load `@post` or `@posts` using the `PostPolicy` with the `:id` param
44
44
  If there is no parent instance variable set (e.g., a non-nested route), it will fall back
45
45
  to the default behavior of scoping with the model class.
46
46
 
47
+ When the association name doesn't match the model name, use the `:association` option:
48
+ ```ruby
49
+ class ArticlesController < ApplicationController
50
+ load_resource model_class: User, parent: true
51
+ load_resource model_class: Article, through: :user, association: :articles
52
+
53
+ # This passes @user.articles instead of @user.posts to the ArticlePolicy::Scope
54
+ end
55
+ ```
56
+
57
+ This is useful when you have associations like `has_many :published_posts, class_name: "Post"`
58
+ or other cases where the association method name differs from the model class name.
59
+
60
+ When the parent relationship attribute in the model uses a different name than the `:through`
61
+ option, use the `:parent_key` option:
62
+
63
+ ```ruby
64
+ class ArticlesController < ApplicationController
65
+ load_resource model_class: User, parent: true
66
+ load_resource model_class: Article, through: :user, parent_key: :admin
67
+
68
+ # This builds Article.new(admin: @user) instead of Article.new(user: @user)
69
+ end
70
+ ```
71
+
72
+ This is useful when the model's foreign key or association attribute name differs from the
73
+ parent's instance name. For example, when `belongs_to :admin, class_name: "User"` or
74
+ `belongs_to :author, class_name: "User"` is used instead of a standard `belongs_to :user`.
75
+
47
76
  #### Customized loading
48
77
 
49
78
  You can customize the loading for cases when the model, controller, and policies don't match up name-wise.
@@ -72,6 +72,18 @@ module PunditCan
72
72
  # the scope passed to the policy will be the parent's association. For example,
73
73
  # +through: :user+ will pass +@user.posts+ as the scope to the PostPolicy.
74
74
  #
75
+ # @param [Symbol] association Optional. When used with +:through+, specifies the association
76
+ # method name to call on the parent. By default, the association name is derived from the
77
+ # model class name (e.g., +Post+ becomes +posts+). Use this option when the association name
78
+ # differs from the model name. For example, +through: :user, association: :articles+ will
79
+ # pass +@user.articles+ as the scope.
80
+ #
81
+ # @param [Symbol] parent_key Optional. When used with +:through+, specifies the associated
82
+ # method on the model and sets the parent. By default the parent_key value = +:through+. Use
83
+ # this when the parent relationship in the model uses a different name.
84
+ # For example, +through: :user, parent_key: :admin+ will
85
+ # pass +Article.new(admin: @user)+ when creating new model instances.
86
+ #
75
87
  # @param [Constant] policy_class Optional. The policy class to use. Defaults from controller name.
76
88
  #
77
89
  # @param [Constant] policy_scope_class Optional. The policy scope class to use. Defaults from controller name.
@@ -97,16 +109,19 @@ module PunditCan
97
109
  policy_kwopts = options.extract!(:policy_class)
98
110
  policy_scope_kwopts = options.extract!(:policy_scope_class)
99
111
 
112
+ parent = instance_variable_get("@#{options[:through]}") if options[:through]
113
+
100
114
  loaded = if options[:parent]
101
115
  load_parent_instance_var(model_class, param_key, policy_kwopts, policy_scope_kwopts)
102
116
  else
103
117
  # When :through is specified, pass the parent's association as the scope
104
- scope_class = if options[:through] && (parent = instance_variable_get("@#{options[:through]}"))
105
- parent.public_send(model_class.name.underscore.pluralize)
118
+ scope_class = if parent
119
+ assoc = options[:association] || model_class.name.underscore.pluralize
120
+ parent.public_send(assoc)
106
121
  else
107
122
  model_class
108
123
  end
109
- load_instance_var(model_class, param_key, policy_kwopts, policy_scope_kwopts, scope_class)
124
+ load_instance_var(model_class, param_key, policy_kwopts, policy_scope_kwopts, scope_class, parent, options[:through] || options[:parent_key])
110
125
  end
111
126
 
112
127
  instance_name = instance_name.pluralize unless loaded.is_a?(model_class)
@@ -127,14 +142,18 @@ module PunditCan
127
142
  options[:model_class].name.underscore if options[:model_class].present? && options[:parent]
128
143
  end
129
144
 
130
- def load_instance_var(model_class, param_key, policy_kwopts, policy_scope_kwopts, scope_class = model_class)
145
+ def load_instance_var(model_class, param_key, policy_kwopts, policy_scope_kwopts, scope_class = model_class, parent = nil, parent_key = nil)
131
146
  case params[:action]
132
147
  when "index"
133
148
  load_scope(scope_class, policy_kwopts, policy_scope_kwopts)
134
- when "new"
135
- authorize(model_class.new, **policy_kwopts)
136
- when "create"
137
- authorize(model_class.new(permitted_attributes(model_class)), **policy_kwopts)
149
+ when "create", "new"
150
+ parent_attributes = {}
151
+ parent_attributes[parent_key] = parent if parent
152
+ if params[:action] == "new"
153
+ authorize(model_class.new(parent_attributes), **policy_kwopts)
154
+ else
155
+ authorize(model_class.new(parent_attributes.merge(permitted_attributes(model_class))), **policy_kwopts)
156
+ end
138
157
  when "edit", "update", "show", "destroy"
139
158
  load_model(scope_class, param_key, policy_kwopts, policy_scope_kwopts)
140
159
  else
@@ -1,3 +1,3 @@
1
1
  module PunditCan
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.5"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pundit_can
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - candland
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-03-18 00:00:00.000000000 Z
11
+ date: 2026-05-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pundit