Sinatra 和 Datamapper 无法将数组保存为数据类型对象

发布于 2024-12-21 21:22:44 字数 4459 浏览 4 评论 0原文

我有一个 HTML 表单,它使用以下 Sinatra 代码来处理 url '/add-artist' 的 POST:

post '/add-artist' do
  if logged_in?
    a = Artist.new
    a.name = params[:name]
    a.website = params[:website]
    a.facebook = params[:facebook]
    a.created_by = session[:user_id]
    a.created_at = Time.now
    a.updated_by = session[:user_id]
    a_updated_at = Time.now
    a.views = 0
    a.save
    @user = User.get session[:user_id]
    @user.artists.push(a.id)
    @user.save
    redirect '/'
  end
end

对象 'a' 正在保存,但 '@user' 没有保存。我想更具体地说,值“@user.artists”没有被更新。如果您需要更多信息,请询问,但我有一种感觉,你们 Ruby 专家会在我提供的代码中找到问题。

更新

这是一些附加信息。我能够在 irb 中重现该错误。首先这是我对“用户”的类定义。

# dm_models.rb
require 'data_mapper'

DataMapper::setup(:default, "sqlite3://#{Dir.pwd}/event_review.db") 

class User
  include DataMapper::Resource

  property :id, Serial
  property :email, String
  property :password, String
  property :user_name, String
  property :birthdate, Date
  property :city, String
  property :state, String
  property :zip, String
  property :geodata, Object
  property :bio, Text
  property :friends, Object
  property :events, Object
  property :event_reviews, Integer
  property :artists, Object
  property :artist_reviews, Integer
  property :venues, Object
  property :venue_reviews, Integer
  property :created_at, DateTime
  property :updated_at, DateTime
  property :views, Integer

  has n, :reviews

end

这是 irb

>> require 'sinatra'
=> true
>> require 'data_mapper'
=> true
>> require './models/dm_models.rb'
=> true
>> require 'geokit'
=> true
>> 
?> include Geokit::Geocoders
=> Object
>> u = User.get 8
=> #<User @id=8 @email="[email protected]" @password="km" @user_name="Katherine Miller" @birthdate=#<Date: 4895485/2,0,2299161> @city="Burbank" @state="CA" @zip="91501" @geodata=#<Geokit::GeoLoc:0x10150d4d8 @street_number=nil, @suggested_bounds=#<Geokit::Bounds:0x10150cf88 @sw=#<Geokit::LatLng:0x10150cd80 @lng=-118.315043, @lat=34.1766949>, @ne=#<Geokit::LatLng:0x10150cee8 @lng=-118.27996, @lat=34.221666>>, @lng=-118.2935891, @zip="91501", @state="CA", @precision="zip", @province=nil, @all=[#<Geokit::GeoLoc:0x10150d4d8 ...>], @street_address=nil, @provider="google", @city="Burbank", @lat=34.2039087, @country_code="US", @full_address="Burbank, CA 91501, USA", @street_name=nil, @accuracy=5, @country="USA", @success=true> @bio=<not loaded> @friends=[] @events=["13", "14", "15", "16", "28", "29"] @event_reviews=7 @artists=[] @artist_reviews=1 @venues=[] @venue_reviews=0 @created_at=#<DateTime: 70729968253/28800,-5/24,2299161> @updated_at=#<DateTime: 1178838019/480,-5/24,2299161> @views=56>
>> 
?> u.artists
=> []
>> u.artists.push "5"
=> ["5"]
>> u.save
=> true
>> u = User.get 8
=> #<User @id=8 @email="[email protected]" @password="km" @user_name="Katherine Miller" @birthdate=#<Date: 4895485/2,0,2299161> @city="Burbank" @state="CA" @zip="91501" @geodata=#<Geokit::GeoLoc:0x1014e8638 @street_number=nil, @suggested_bounds=#<Geokit::Bounds:0x1014e80e8 @sw=#<Geokit::LatLng:0x1014e7eb8 @lng=-118.315043, @lat=34.1766949>, @ne=#<Geokit::LatLng:0x1014e8048 @lng=-118.27996, @lat=34.221666>>, @lng=-118.2935891, @zip="91501", @state="CA", @precision="zip", @province=nil, @all=[#<Geokit::GeoLoc:0x1014e8638 ...>], @street_address=nil, @provider="google", @city="Burbank", @lat=34.2039087, @country_code="US", @full_address="Burbank, CA 91501, USA", @street_name=nil, @accuracy=5, @country="USA", @success=true> @bio=<not loaded> @friends=[] @events=["13", "14", "15", "16", "28", "29"] @event_reviews=7 @artists=[] @artist_reviews=1 @venues=[] @venue_reviews=0 @created_at=#<DateTime: 70729968253/28800,-5/24,2299161> @updated_at=#<DateTime: 1178838019/480,-5/24,2299161> @views=56>
>> u.artists
=> []
>> u.artists.class
=> Array

上面代码的描述:我检索 id==8 的用户,将值“5”推入其中。这看起来是成功的。我保存了用户#8。然后我重新检索 user#8 并查看艺术家值,它是一个空数组。

最后,我可以更新其他字段,例如“artist_reviews”。这是因为我将艺术家、活动和场地的数据类型定义为“对象”吗?所有这些领域都存在这个问题。

感谢您的帮助。

I have an HTML form which uses the following Sinatra code to handle POST for the url '/add-artist':

post '/add-artist' do
  if logged_in?
    a = Artist.new
    a.name = params[:name]
    a.website = params[:website]
    a.facebook = params[:facebook]
    a.created_by = session[:user_id]
    a.created_at = Time.now
    a.updated_by = session[:user_id]
    a_updated_at = Time.now
    a.views = 0
    a.save
    @user = User.get session[:user_id]
    @user.artists.push(a.id)
    @user.save
    redirect '/'
  end
end

The object 'a' is being saved but '@user' is not. I guess more specifically, the value '@user.artists' is not being updated. If you need more info, please ask but I have a feeling that you Ruby vets will find the problem in the code I provided.

UPDATE

Here's some additional info. I was able to reproduce the error in irb. First here's my class definition for 'User'.

# dm_models.rb
require 'data_mapper'

DataMapper::setup(:default, "sqlite3://#{Dir.pwd}/event_review.db") 

class User
  include DataMapper::Resource

  property :id, Serial
  property :email, String
  property :password, String
  property :user_name, String
  property :birthdate, Date
  property :city, String
  property :state, String
  property :zip, String
  property :geodata, Object
  property :bio, Text
  property :friends, Object
  property :events, Object
  property :event_reviews, Integer
  property :artists, Object
  property :artist_reviews, Integer
  property :venues, Object
  property :venue_reviews, Integer
  property :created_at, DateTime
  property :updated_at, DateTime
  property :views, Integer

  has n, :reviews

end

Here is the irb

>> require 'sinatra'
=> true
>> require 'data_mapper'
=> true
>> require './models/dm_models.rb'
=> true
>> require 'geokit'
=> true
>> 
?> include Geokit::Geocoders
=> Object
>> u = User.get 8
=> #<User @id=8 @email="[email protected]" @password="km" @user_name="Katherine Miller" @birthdate=#<Date: 4895485/2,0,2299161> @city="Burbank" @state="CA" @zip="91501" @geodata=#<Geokit::GeoLoc:0x10150d4d8 @street_number=nil, @suggested_bounds=#<Geokit::Bounds:0x10150cf88 @sw=#<Geokit::LatLng:0x10150cd80 @lng=-118.315043, @lat=34.1766949>, @ne=#<Geokit::LatLng:0x10150cee8 @lng=-118.27996, @lat=34.221666>>, @lng=-118.2935891, @zip="91501", @state="CA", @precision="zip", @province=nil, @all=[#<Geokit::GeoLoc:0x10150d4d8 ...>], @street_address=nil, @provider="google", @city="Burbank", @lat=34.2039087, @country_code="US", @full_address="Burbank, CA 91501, USA", @street_name=nil, @accuracy=5, @country="USA", @success=true> @bio=<not loaded> @friends=[] @events=["13", "14", "15", "16", "28", "29"] @event_reviews=7 @artists=[] @artist_reviews=1 @venues=[] @venue_reviews=0 @created_at=#<DateTime: 70729968253/28800,-5/24,2299161> @updated_at=#<DateTime: 1178838019/480,-5/24,2299161> @views=56>
>> 
?> u.artists
=> []
>> u.artists.push "5"
=> ["5"]
>> u.save
=> true
>> u = User.get 8
=> #<User @id=8 @email="[email protected]" @password="km" @user_name="Katherine Miller" @birthdate=#<Date: 4895485/2,0,2299161> @city="Burbank" @state="CA" @zip="91501" @geodata=#<Geokit::GeoLoc:0x1014e8638 @street_number=nil, @suggested_bounds=#<Geokit::Bounds:0x1014e80e8 @sw=#<Geokit::LatLng:0x1014e7eb8 @lng=-118.315043, @lat=34.1766949>, @ne=#<Geokit::LatLng:0x1014e8048 @lng=-118.27996, @lat=34.221666>>, @lng=-118.2935891, @zip="91501", @state="CA", @precision="zip", @province=nil, @all=[#<Geokit::GeoLoc:0x1014e8638 ...>], @street_address=nil, @provider="google", @city="Burbank", @lat=34.2039087, @country_code="US", @full_address="Burbank, CA 91501, USA", @street_name=nil, @accuracy=5, @country="USA", @success=true> @bio=<not loaded> @friends=[] @events=["13", "14", "15", "16", "28", "29"] @event_reviews=7 @artists=[] @artist_reviews=1 @venues=[] @venue_reviews=0 @created_at=#<DateTime: 70729968253/28800,-5/24,2299161> @updated_at=#<DateTime: 1178838019/480,-5/24,2299161> @views=56>
>> u.artists
=> []
>> u.artists.class
=> Array

The description of the above code: I retrieve user with id==8, push the value "5" into it. This appears to be successful. I save user#8. Then I re-retrieve user#8 and look at the artists value and it is an empty array.

And finally, I am able to update other fields like "artist_reviews". Is this because I am defining the datatype to be 'Object' for artists, events and venues? This problem exists for all of those fields.

Thanks for the help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小矜持 2024-12-28 21:22:44

日志说什么?你可以推送到@user.artists吗?它是一个数组吗?它可能会验证失败并且您无法完成保存。

What do the logs say? Can you push to @user.artists? Is it an Array? It might fail validation and you cannot complete save.

樱花落人离去 2024-12-28 21:22:44

我不久前问过这个问题,但我很确定解决方案是序列化对象。在本例中,它是一个整数数组。我不确定是否有时间用详细的解决方案来更新它,但数组不能直接存储在关系数据库中。数组对象必须是“序列化”的,本质上是转换为字符串。在此示例中,artist 属性的数据类型将为 text。

您可以手动将 Artist 列转换为数组(从字符串),将新整数推送到数组,然后转换回字符串并保存。我假设有一种自动化的方法可以做到这一点,但这就是想法。

此外,整个示例处理关联的方式很糟糕。更好的方法是建立一对多关联,其中有一个 ArtistUser 表,其中包含两列 artist_iduser_id 。每个新关联都表示为 ArtistUser 表中的一个新行。

I asked this a while ago but I'm pretty certain the solution is to serialize the object. In this case it was an array of integers. I'm not sure if I'll have the time to update this with a detailed solution but an array cannot be stored directly in a relational database. The array object must be 'serialized', essentially converted to a string. In this example the datatype for the artist attribute would then be text.

You could manually convert the artist column to an array (from string) push the new integer(s) into the array and then convert back to string and save. I'm assuming there is an automated way to do this but that's the idea.

Furthermore, this entire example is a poor way to handle associations. The better way to do this is to have a one-to-many association where there is an ArtistUser table which has two columns artist_id and user_id. Every new association is represented as a new row in the ArtistUser table.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文