【发布时间】:2020-07-26 09:19:21
【问题描述】:
我目前正在将我的 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.rb 模型中添加
belongs_to :label关联。不幸的是,它没有改变任何东西。
我在下面附上我的链接模型:
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
还有我的标签模型:
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 模型中所述,答案始终是肯定的或 nil。引发错误的唯一问题是检查 @label.links
例如:
>> @label.conversations
=> #<ActiveRecord::Associations::CollectionProxy []>
>> @label.name
=> "Test Label"
>> @label.links
!! #<NoMethodError: undefined method `extensions' for #<Hash:0x000000001001f1e8>
Did you mean? extend>
感谢您对我的帮助!
【问题讨论】:
-
您应该更改
Label::PersonalInformationsController的定义以使用显式嵌套,因为使用范围解析运算符会导致意外的常量查找。我并不是说它是您当前困境的原因,而是一堆等待发生的错误。 github.com/rubocop-hq/ruby-style-guide#namespace-definition -
嘿,麦克斯。感谢您的意见。我现在正在根据您附加的样式指南在我的整个应用程序中更改它。
-
如果您使用的是Rubocop,有一位名叫ClassAndModuleChildren 的警察可以帮助您。
-
有同样的问题,但与 HABTM 关联。已将其追溯到associations.rb:
extensions |= reflection.scope_for(klass.unscoped, owner).extensions -
完成@MyKoryto 我的症状相似,但原因不同
标签: ruby-on-rails model controller ruby-on-rails-6