Model associations problem: NoMethodError: undefined method `extensions' for #<Hash...>
Model associations problem: NoMethodError: undefined method `extensions' for #<Hash...>
我目前正在将我的 rails 5.2 应用程序升级到 rails 6.0,同时遵循 upgrading guide.
在我的一位用户 类(唱片公司或艺术家)与链接模型交互时遇到错误之前,一切似乎都运行良好。
当我尝试注册为艺人或唱片公司时,当我需要定义指向用户社交媒体或网站的链接时收到以下错误消息:
Completed 500 Internal Server Error in 139ms (ActiveRecord: 7.3ms | Allocations: 14518)
NoMethodError - undefined method `extensions' for #<Hash:0x000000000bdd4ec8>
Did you mean? extend:
app/controllers/label/personal_informations_controller.rb:8:in `edit'
这是我的personal_informations_controller:(错误在第 8 行,我将标记出来以便清楚)
class Label::PersonalInformationsController < LabelController
layout "signup"
skip_before_action :ensure_approved
def edit
prepare_country_options
@label = current_label
@label.links.build(links_attributes) #***ERROR OCCURS HERE***#
end
def update
@label = current_label
if @label.update_attributes(label_params)
redirect_to edit_label_genres_path
else
update_error
end
end
private
def update_error
prepare_country_options
@label.links.build(links_attributes)
render :edit
end
def label_params
params.require(:label).permit(:logo, :city, :country_code, :profile, links_attributes: [:id, :source, :url])
end
def prepare_country_options
@country_options ||= Countries.prioritized.map { |country| [country.name, country.code] }
end
def links_attributes
link_sources.map { |source| {source: source } }
end
def link_sources
Link.sources - @label.links.map(&:source)
end
end
到目前为止,我已经尝试了 3 种解决方案:
- 检查这个错误是否与默认自动加载器更改为 Zeitwerk 有任何关系,在检查了一段时间后我得出的结论是它与它没有任何关系。
- 检查此错误是否与我使用 Discogs API 的事实有关,以便在可能的情况下为新用户自动提取链接。但是,当我提到 @label.links 以专门指向我的服务目录中的 Discogs 文件时,它搞砸了一切,因为它不再指向它应该指向的 'Link' 模型。
- 在我的 link.rb 模型中添加
belongs_to :label
关联。不幸的是,它没有改变任何东西。
我在下面附上我的 Link 模型:
class Link < ApplicationRecord
LINKS_ORDERED = ['website', 'facebook', 'twitter', 'youtube', 'soundcloud', 'lastfm']
def self.ordered_links
ret = "CASE"
LINKS_ORDERED.each_with_index do |p, i|
ret << " WHEN source = '#{p}' THEN #{i}"
end
ret << " END"
end
validates :url, presence: true
default_scope { {order: ordered_links} }
def self.website
where(source: "website" )
end
def self.sources
["website", "facebook", "twitter", "youtube", "soundcloud", "lastfm"]
end
def self.icons
["globe", "facebook", "twitter", "youtube", "soundcloud", "lastfm"]
end
def to_partial_path
"links/#{source}"
end
def account_name
is_social_account? ? url.split("/").last : domain
end
def source
read_attribute(:source) # guessed_source || ...
end
def icon
self.class.icons[self.class.sources.index(source)]
end
def url=(url)
url = "http://#{url}" unless url =~ /^https?\:\/\//
write_attribute(:url, url)
end
private
def is_social_account?
(self.class.sources - ["website"]).include? source
end
def guessed_source
self.class.sources.find { |source| url =~ /#{source}/ }
end
def domain
url.gsub(/https?\:\/\//, "").split("/").first
end
end
还有我的 Label 模型:
class Label < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable
include PgSearch::Model
has_attached_file :logo, :s3_protocol => :https,
styles: { medium: "350x360#", thumb: "40x40#" },
default_url: ":class/:attachment/missing_:style.jpg"
validates_attachment_content_type :logo, content_type: %r{\Aimage/.*\Z}
alias_method :avatar, :logo
has_and_belongs_to_many :genres
has_many :feedback_requests
has_many :payment_types, as: :payee
has_many :links, as: :linkable, dependent: :destroy
has_many :releases
has_many :label_artists
has_many :sent_messages, as: :from, class_name: "Message"
has_many :messages, through: :conversations
has_many :conversations
has_many :songs, through: :feedback_requests, source: :song
has_many :artist_contacts, through: :songs, source: :artist
has_many :contracts, through: :conversations
accepts_nested_attributes_for :payment_types
accepts_nested_attributes_for :links, reject_if: ->(attributes) { attributes[:url].blank? }
validates :name, :real_name, presence: true
validates :city, :country_code, :profile, presence: true, on: :update
delegate :name, to: :country, prefix: true, allow_nil: true
pg_search_scope :search,
against: :name,
associated_against: { genres: :name },
using: {
tsearch: { dictionary: :english }
}
pg_search_scope :by_relevance,
associated_against: { genres: :name },
using: {
tsearch: { dictionary: :english, any_word: true }
}
def self.approved
where("approved_at IS NOT NULL")
end
def approved?
approved_at.present?
end
def payment_type
payment_types.order("created_at").last
end
def display_name
name
end
def country
Country.new(code: country_code)
end
def location
[city, country_name].compact.join(", ")
end
def logo_url(style = :medium)
logo.url(style)
end
# The profit the label has earned (deducting Sendemo's cut)
def balance_net
((raw_balance.to_i/100.0) * (1-Payment.sendemo_fee_fraction)).round(2) if raw_balance.present?
end
# A label's balance is the entire balance charged through the label including Sendemo's fee.
# This is for backwards compatibility and should be changed
def balance=(new_balance)
write_attribute(:balance, (new_balance.to_f*100).to_i) if new_balance.present?
end
def balance
(raw_balance.to_i/100.0).round(2) if raw_balance.present?
end
def raw_balance
read_attribute(:balance)
end
def unread_messages_count
messages.unread.count
end
def unread_messages?
unread_messages_count > 0
end
end
值得一提的是,当我尝试在 rails 控制台中写入以查看我的 current_label 是否有任何其他 属性 它应该如我在标签模型,答案总是肯定的或零。引发错误的唯一问题是在检查 @label.links
时
例如:
>> @label.conversations
=> #<ActiveRecord::Associations::CollectionProxy []>
>> @label.name
=> "Test Label"
>> @label.links
!! #<NoMethodError: undefined method `extensions' for #<Hash:0x000000001001f1e8>
Did you mean? extend>
谢谢你的帮助!
我遇到了类似的问题,我的是这样的:
class Foo < ApplicationRecord
has_and_belongs_to_many :bars, -> { uniq }
end
当我在 Foo 上调用 .bars
时,出现 undefined_method: extensions
错误。
我的解决方案是在 Rails 6 迁移期间将 -> { uniq }
更改为 -> { distinct }
。
希望这对某人有所帮助。
毕竟解决方案非常简单。 rails 5.2 和 rails 6.0 之间的范围部分似乎发生了变化。
Rails 5.2 仍然支持一种在 rails 3 中即将弃用的语法,而 rails 6.0 不再支持这种语法。
在 link.rb(我的 link 模型)第 15 行我定义范围时出现问题:
default_scope { {order: ordered_links} }
对我有用的新语法如下:
default_scope { order(ordered_links) }
信息取自here.
Koryto 先生的回答看起来并不相同 - 何时设置默认值 ORDER BY
,另一个默认值 WHERE
。也许你应该试试
default_scope { order(ordered_links) }
我目前正在将我的 rails 5.2 应用程序升级到 rails 6.0,同时遵循 upgrading guide.
在我的一位用户 类(唱片公司或艺术家)与链接模型交互时遇到错误之前,一切似乎都运行良好。
当我尝试注册为艺人或唱片公司时,当我需要定义指向用户社交媒体或网站的链接时收到以下错误消息:
Completed 500 Internal Server Error in 139ms (ActiveRecord: 7.3ms | Allocations: 14518)
NoMethodError - undefined method `extensions' for #<Hash:0x000000000bdd4ec8>
Did you mean? extend:
app/controllers/label/personal_informations_controller.rb:8:in `edit'
这是我的personal_informations_controller:(错误在第 8 行,我将标记出来以便清楚)
class Label::PersonalInformationsController < LabelController
layout "signup"
skip_before_action :ensure_approved
def edit
prepare_country_options
@label = current_label
@label.links.build(links_attributes) #***ERROR OCCURS HERE***#
end
def update
@label = current_label
if @label.update_attributes(label_params)
redirect_to edit_label_genres_path
else
update_error
end
end
private
def update_error
prepare_country_options
@label.links.build(links_attributes)
render :edit
end
def label_params
params.require(:label).permit(:logo, :city, :country_code, :profile, links_attributes: [:id, :source, :url])
end
def prepare_country_options
@country_options ||= Countries.prioritized.map { |country| [country.name, country.code] }
end
def links_attributes
link_sources.map { |source| {source: source } }
end
def link_sources
Link.sources - @label.links.map(&:source)
end
end
到目前为止,我已经尝试了 3 种解决方案:
- 检查这个错误是否与默认自动加载器更改为 Zeitwerk 有任何关系,在检查了一段时间后我得出的结论是它与它没有任何关系。
- 检查此错误是否与我使用 Discogs API 的事实有关,以便在可能的情况下为新用户自动提取链接。但是,当我提到 @label.links 以专门指向我的服务目录中的 Discogs 文件时,它搞砸了一切,因为它不再指向它应该指向的 'Link' 模型。
- 在我的 link.rb 模型中添加
belongs_to :label
关联。不幸的是,它没有改变任何东西。
我在下面附上我的 Link 模型:
class Link < ApplicationRecord
LINKS_ORDERED = ['website', 'facebook', 'twitter', 'youtube', 'soundcloud', 'lastfm']
def self.ordered_links
ret = "CASE"
LINKS_ORDERED.each_with_index do |p, i|
ret << " WHEN source = '#{p}' THEN #{i}"
end
ret << " END"
end
validates :url, presence: true
default_scope { {order: ordered_links} }
def self.website
where(source: "website" )
end
def self.sources
["website", "facebook", "twitter", "youtube", "soundcloud", "lastfm"]
end
def self.icons
["globe", "facebook", "twitter", "youtube", "soundcloud", "lastfm"]
end
def to_partial_path
"links/#{source}"
end
def account_name
is_social_account? ? url.split("/").last : domain
end
def source
read_attribute(:source) # guessed_source || ...
end
def icon
self.class.icons[self.class.sources.index(source)]
end
def url=(url)
url = "http://#{url}" unless url =~ /^https?\:\/\//
write_attribute(:url, url)
end
private
def is_social_account?
(self.class.sources - ["website"]).include? source
end
def guessed_source
self.class.sources.find { |source| url =~ /#{source}/ }
end
def domain
url.gsub(/https?\:\/\//, "").split("/").first
end
end
还有我的 Label 模型:
class Label < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable
include PgSearch::Model
has_attached_file :logo, :s3_protocol => :https,
styles: { medium: "350x360#", thumb: "40x40#" },
default_url: ":class/:attachment/missing_:style.jpg"
validates_attachment_content_type :logo, content_type: %r{\Aimage/.*\Z}
alias_method :avatar, :logo
has_and_belongs_to_many :genres
has_many :feedback_requests
has_many :payment_types, as: :payee
has_many :links, as: :linkable, dependent: :destroy
has_many :releases
has_many :label_artists
has_many :sent_messages, as: :from, class_name: "Message"
has_many :messages, through: :conversations
has_many :conversations
has_many :songs, through: :feedback_requests, source: :song
has_many :artist_contacts, through: :songs, source: :artist
has_many :contracts, through: :conversations
accepts_nested_attributes_for :payment_types
accepts_nested_attributes_for :links, reject_if: ->(attributes) { attributes[:url].blank? }
validates :name, :real_name, presence: true
validates :city, :country_code, :profile, presence: true, on: :update
delegate :name, to: :country, prefix: true, allow_nil: true
pg_search_scope :search,
against: :name,
associated_against: { genres: :name },
using: {
tsearch: { dictionary: :english }
}
pg_search_scope :by_relevance,
associated_against: { genres: :name },
using: {
tsearch: { dictionary: :english, any_word: true }
}
def self.approved
where("approved_at IS NOT NULL")
end
def approved?
approved_at.present?
end
def payment_type
payment_types.order("created_at").last
end
def display_name
name
end
def country
Country.new(code: country_code)
end
def location
[city, country_name].compact.join(", ")
end
def logo_url(style = :medium)
logo.url(style)
end
# The profit the label has earned (deducting Sendemo's cut)
def balance_net
((raw_balance.to_i/100.0) * (1-Payment.sendemo_fee_fraction)).round(2) if raw_balance.present?
end
# A label's balance is the entire balance charged through the label including Sendemo's fee.
# This is for backwards compatibility and should be changed
def balance=(new_balance)
write_attribute(:balance, (new_balance.to_f*100).to_i) if new_balance.present?
end
def balance
(raw_balance.to_i/100.0).round(2) if raw_balance.present?
end
def raw_balance
read_attribute(:balance)
end
def unread_messages_count
messages.unread.count
end
def unread_messages?
unread_messages_count > 0
end
end
值得一提的是,当我尝试在 rails 控制台中写入以查看我的 current_label 是否有任何其他 属性 它应该如我在标签模型,答案总是肯定的或零。引发错误的唯一问题是在检查 @label.links
时例如:
>> @label.conversations
=> #<ActiveRecord::Associations::CollectionProxy []>
>> @label.name
=> "Test Label"
>> @label.links
!! #<NoMethodError: undefined method `extensions' for #<Hash:0x000000001001f1e8>
Did you mean? extend>
谢谢你的帮助!
我遇到了类似的问题,我的是这样的:
class Foo < ApplicationRecord
has_and_belongs_to_many :bars, -> { uniq }
end
当我在 Foo 上调用 .bars
时,出现 undefined_method: extensions
错误。
我的解决方案是在 Rails 6 迁移期间将 -> { uniq }
更改为 -> { distinct }
。
希望这对某人有所帮助。
毕竟解决方案非常简单。 rails 5.2 和 rails 6.0 之间的范围部分似乎发生了变化。
Rails 5.2 仍然支持一种在 rails 3 中即将弃用的语法,而 rails 6.0 不再支持这种语法。
在 link.rb(我的 link 模型)第 15 行我定义范围时出现问题:
default_scope { {order: ordered_links} }
对我有用的新语法如下:
default_scope { order(ordered_links) }
信息取自here.
Koryto 先生的回答看起来并不相同 - 何时设置默认值 ORDER BY
,另一个默认值 WHERE
。也许你应该试试
default_scope { order(ordered_links) }