Reputation: 556
I tried everything but cannot make heads or tails of this ruby on rails in ´def new´ methode.
def edge_params
params.require(:edge).permit(:kind, :start_id, :end_id, :property1)
end
This way the parameters end up at the ´Edge.save(edge_params)´ methode but ´:start_id´ and ´:end_id´ are foreign keys that both point to a Node.
def edge_params
params.require(:edge).permit(:kind, :start_id, :end_id, :property1)
p = {
:kind => params[:kind],
:start_id => Node.where("nodeid = ?", params[:start_id]).first,
:end_id => Node.where("nodeid = ?", params[:end_id]).first,
:property1 => params[:property1]
}
end
This executes but it always fails with complaining that all the required (validate presence of kind, start/end_id) are blank. I am doing something wrong here. I need to somehow find the Node ID because otherwise I get the expected Node but got String error. I am new to Ruby and it is quite a lot more difficult than it looks because it does so many things implicitly that one doesn't really know what one is doing. But it needs a ruby hash for the .save methode as much as i could figure out.
I also don't fully understand the require permit part. I got this from the tutorial on the rails page. Would params.require(:edge => [:kind,:start_id,:end_id]).permit(:property1) work too because that would make more logical sense for my data.
Additional Info
class Edge < ActiveRecord::Base
belongs_to :start_id, :class_name => 'Node', :foreign_key => "start_id", :primary_key => "nodeid"
belongs_to :end_id, :class_name => 'Node', :foreign_key => "end_id", :primary_key => "nodeid"
validates :kind, presence: true
validates :start_id, presence: true
validates :end_id, presence: true
end
class Node < ActiveRecord::Base
has_many :start_id, :class_name => 'Edge', :foreign_key => "start_id" , :primary_key => "nodeid"
has_many :end_id, :class_name => 'Edge', :foreign_key => "end_id", :primary_key => "nodeid"
validates :nodeid, presence: true, uniqueness: true, length: { minimum: 2 }
end
<%= form_for @edge do |f| %>
<p>
<%= f.label :kind %><br>
<%= f.text_field :kind %>
</p>
<p>
<%= f.label :start_id %><br>
<%= f.text_field :start_id %>
</p>
<p>
<%= f.label :end_id %><br>
<%= f.text_field :end_id %>
</p>
<p>
<%= f.label :propety1 %><br>
<%= f.text_field :property1 %>
</p>
Upvotes: 0
Views: 136
Reputation: 29598
First your classes seem a bit off try this
class Edge < ActiveRecord::Base
belongs_to :start_node, :class_name => 'Node', :foreign_key => "start_id", :primary_key =>"nodeid"
belongs_to :end_node, :class_name => 'Node', :foreign_key => "end_id", :primary_key =>"nodeid"
validates :kind, presence: true
validates :start_id, presence: true
validates :end_id, presence: true
end
class Node < ActiveRecord::Base
has_many :start_edges, :class_name => 'Edge', :foreign_key => "start_id", :primary_key =>"nodeid"
has_many :end_edges, :class_name => 'Edge', :foreign_key => "end_id", :primary_key =>"nodeid"
validates :nodeid, presence: true, uniqueness: true, length: { minimum: 2 }
end
why are you building a Hash
after the require? This should work fine.
def create
@edge = Edge.new(edge_params)
if @edge.save
redirect_to edge_path(@edge)
else
render 'new'
end
end
private
def edge_params
params.require(:edge).permit(:kind,:start_id,:end_id,:property1)
end
There is not need to submit the nodes as actual Node
objects. This association is made in the model through ORM (Object Relational Mapping). When you call @edge.start_node
it will execute a query that looks like
"SELECT nodes.* FROM nodes where nodes.nodeid = THIS EDGES START_ID"
Also I am sure there is some reason that you are using nodeid
in place of the standard id
column but I wouldn't recommend it. I would make the associations like this instead.
class Edge < ActiveRecord::Base
belongs_to :start_node, :class_name => 'Node', :foreign_key => "start_id"
belongs_to :end_node, :class_name => 'Node', :foreign_key => "end_id"
validates :kind, presence: true
validates :start_id, presence: true
validates :end_id, presence: true
end
class Node < ActiveRecord::Base
has_many :start_edges, :class_name => 'Edge', :foreign_key => "start_id"
has_many :end_edges, :class_name => 'Edge', :foreign_key => "end_id"
validates :nodeid, presence: true, uniqueness: true, length: { minimum: 2 }
end
Then Edge
and Node
will be associated through a incremented column called id
that is built into Rails
tables by default. The reason being is if you allow a user to change the nodeid
on a Node
it will break the realtionship chain to Edge
where as using id
the nodeid
can change but it's relationships stay intact.
I would also recommend changing your form to use select boxes because you are not validating the existence of a Node
at all right now but that seems like a separate issue.
To answer your question in the comments I would use a view like this.
<%= form_for @edge do |f| %>
<p>
<%= f.label :kind %><br>
<%= f.text_field :kind %>
</p>
<p>
<%= f.label :start_id %><br>
<%= collection_select(:edge,:start_id,Node.all,:id,:nodeid) %>
</p>
<p>
<%= f.label :end_id %><br>
<%= collection_select(:edge,:end_id,Node.all,:id,:nodeid) %>
</p>
<p>
<%= f.label :propety1 %><br>
<%= f.text_field :property1 %>
</p>
<%= f.submit %>
<% end %>
Upvotes: 1