所以我正在尝试创建一个应用程序,允许用户创建项目列表并仅查看他们自己创建的列表。每次我按表格上的提交都会发生这种情况
Started POST "/lists" for 127.0.0.1 at 2017-08-18 15:56:40 -0400
Processing by ListsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"VnsMdQq3mw5XabkYCZFTgvgwFc3H89paHA0VE5gunFbiMfa0xGr0p1GEZDHc3yemwBx07K1h4CXuS0l5XL1VbA==", "list"=>{"income"=>"12", "put_into_savings"=>"12", "month"=>"12", "year"=>"21"}, "commit"=>"Create List"}
(0.1ms) begin transaction
(0.1ms) rollback transaction
(0.0ms) begin transaction
(0.0ms) rollback transaction
Rendering lists/new.html.erb within layouts/application
Rendered lists/new.html.erb within layouts/application (9.3ms)
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 5], ["LIMIT", 1]]
Completed 200 OK in 269ms (Views: 222.2ms | ActiveRecord: 2.7ms)
这是我的所有代码:
lists_controller.rb
class ListsController < ApplicationController
def show
@user = User.find(params[:id])
@lists = @user.lists
end
def new
end
def edit
end
def create
@list = List.create(list_params)
if @list.save
redirect_to home_url
else
render :new
end
end
private
def list_params
params.require(:list).permit(:income, :put_into_savings, :month, :year)
end
end
列表/ new.html.erb
<%= form_for List.new do |f| %>
<div class="field">
<%= f.label :income %><br />
<%= f.text_field :income %>
</div>
<div class="field">
<%= f.label :put_into_savings %><br />
<%= f.text_area :put_into_savings %>
</div>
<div class="field">
<%= f.label :month %><br />
<%= f.number_field :month %>
</div>
<div class="field">
<%= f.label :year %><br />
<%= f.number_field :year %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
schema.rb
ActiveRecord::Schema.define(version: 20170818185700) do
create_table "items", force: :cascade do |t|
t.string "item_name"
t.integer "item_cost"
t.string "item_waste"
t.string "item_group"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "lists", force: :cascade do |t|
t.integer "income"
t.integer "put_into_savings"
t.string "month"
t.string "year"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "Item_id"
t.integer "User_id"
end
create_table "users", force: :cascade do |t|
t.string "email"
t.string "password_digest"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "name"
end
end
的routes.rb
Rails.application.routes.draw do
root 'home#index'
get 'home' => 'home#index'
resources :lists
resources :sessions, only: [:new, :create, :destroy]
resources :users, only: [:new, :create]
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
编辑:这是我的列表模型,抱歉早先忘记了
class List < ApplicationRecord
has_many :items
belongs_to :user
end
我对红宝石很新,所以我希望这不是太容易解决的问题,感谢先进的所有帮助,我真的很感激
答案 0 :(得分:1)
您的模型关联存在逻辑问题。
假设List可以有多个Item,您不应该使用属性item_id声明表List。 (这样做意味着列表只能有一个项目)。我建议你阅读ruby-on-rais-guide-for-associations。
对于user_id的问题,您需要在列表对象中显式声明user_id(考虑到您希望在创建List时将List与User关联)。一种方法可以是:
def create
@list = List.new(list_params)
@list[:user_id] = current_user.id # Considering you add this method
if @list.save
redirect_to home_url
else
render :new
end
在模型中添加一些验证:
class List < ApplicationRecord
has_many :items
belongs_to :user
validates :user_id, presence: true
end
您似乎还需要阅读有关验证的更多信息ruby-on-rais-guide-for-validation。关于你的两次回滚,目前还不清楚原因,但修复你的关联和验证问题,我认为你可以解决它。
尝试阅读有关rails的更多信息,您遇到的问题非常基本。祝你好运!
<强>更新强>:
根据at0misk的回答,解决了两次回滚的问题:
在列表控制器中:
@list = List.new(list_params)
# instead of @list = List.create(list_params)
create方法创建一个新对象并立即保存。因此,rails试图保存两次,首先在方法创建中,然后在方法中保存顺序。
答案 1 :(得分:0)
在您的create方法中,您调用create然后调用save。 Create创建一个对象并将其保存到数据库中,因此调用save是redundent。
您是否检查过您的记录是否正在保存?如果是的话那肯定是错的。我更喜欢使用这种模式,使用new而不是create,然后尝试保存在if块中:
import 'package:flutter/material.dart';
import 'dart:ui' as ui;
void main() {
runApp(new MaterialApp(home: new HomePage()));
}
class HomePage extends StatefulWidget {
@override
HomePageState createState() => new HomePageState();
}
class HomePageState extends State<HomePage> with TickerProviderStateMixin {
AnimationController _controller;
Animation<double> _animation;
bool upDown = true;
@override
void initState() {
_controller = new AnimationController(
vsync: this,
duration: const Duration(milliseconds: 180),
);
_animation = new CurvedAnimation(
parent: _controller,
curve: new Interval(0.0, 1.0, curve: Curves.linear),
);
}
@override
Widget build(BuildContext context) {
final ui.Size logicalSize = MediaQuery.of(context).size;
final double _width = logicalSize.width;
final double _height = logicalSize.height;
void _up(){
setState((){
if(upDown) {
upDown = false;
_controller.forward(from: 0.0);
} else {
upDown = true;
_controller.reverse(from: 1.0);
}
});
}
return new Scaffold(
body: new Stack(
children: <Widget>[
new Positioned(
bottom: 0.0,
child: new GestureDetector(
onTap: _up,
child: new AnimatedBuilder(
animation: _animation,
builder: (BuildContext context, Widget child) {
return new Container(
height: _height,
child: new CustomPaint(
painter: new Sky(_width, _height * _animation.value),
child: new Container(
height: _isRotated ? 0.0 : _height * _animation.value,
width: _isRotated ? 0.0 : _width,
),
),
);
},
),
)
),
new Positioned(
bottom: 16.0,
right: 16.0,
child: new FloatingActionButton(
backgroundColor: new Color(0xFFE57373),
child: new Icon(Icons.add),
onPressed: (){
_up();
},
)
)
]
)
);
}
}
class Sky extends CustomPainter {
final double _width;
double _rectHeight;
Sky(this._width, this._rectHeight);
@override
void paint(Canvas canvas, Size size) {
canvas.drawRect(
new Rect.fromLTRB(
0.0, size.height - _rectHeight, this._width, size.height
),
new Paint()..color = new Color.fromRGBO(0, 153, 255, 0.9)
);
}
@override
bool shouldRepaint(Sky oldDelegate) {
return _width != oldDelegate._width || _rectHeight != oldDelegate._rectHeight;
}
}