I am trying to make a form for storing data hierarchy through the associations.
My structure of database is
meta
- ID (PK)
version
- meta_id (FK of meta)
- ID (PK)
- lang (FK from lang ...)
- ....
data
- ID (FK of version)
I need to store multiple language content under one ID.
Models are
class Meta < Sequel::Model(:link_meta)
one_to_many :version
end
class Version < Sequel::Model(:link_version)
one_to_one :meta, key: :meta_id
one_to_many :data, key: :id
one_to_one :lang, key: :lang
end
class Link < Sequel::Model(:link)
plugin :timestamps, :create => :created, :update => :updated
many_to_one :version, key: :id
end
And my form for creating input is.
<% form_for :links, url(:links, :create), :class => 'form-horizontal' do |f| %>
<%= partial 'links/form', :locals => { :f => f } %>
<% end %>
And this is my partial
<% f.fields_for :version, :class => 'form-horizontal' do |cz| %>
<%= cz.hidden_field :lang, :value => Lang.select(:id).where(:lang => "cz").map(:id) %>
<% cz.fields_for :data, :class => 'form-horizontal' do |link| %>
<% error = #links.errors.key?(:url) && #links.errors[:url].count > 0 %>
<fieldset class='control-group <%= error ? 'has-error' : ''%>'>
... form content
</fieldset>
<% end %>
<% f.fields_for :version, :class => 'form-horizontal' do |en| %>
<%= en.hidden_field :lang, :value => Lang.select(:id).where(:lang => "cz").map(:id) %>
<% en.fields_for :data, :class => 'form-horizontal' do |link| %>
<% error = #links.errors.key?(:url) && #links.errors[:url].count > 0 %>
<fieldset class='control-group <%= error ? 'has-error' : ''%>'>
... another form content
</fieldset>
<% end %>
<% end %>
But it fails on
undefined method `data' for [:class, "form-horizontal"]:Array
I tried different association combinations etc, I feel lost.
Thanks
Levi
Related
I have a problem with simple_form's associations.
Here are the models "linked"
class Contact < ApplicationRecord
belongs_to :state
end
class State < ApplicationRecord
CATEGORIES = [ "not-contacted", "on-going", "called"]
has_many :contacts
validates :category, inclusion: { in: CATEGORIES }
end
I have also a State seed with the three states above.
I'm creating the new form for a contact.
Controller :
def new
#contact = Contact.new
#states = State.all
end
def create
#contact = Contact.new(contact_params)
if #contact.save
redirect_to contact_path(params[:id])
else
render :new
end
end
View:
<%= simple_form_for(#contact) do |f| %>
<%= f.input :last_name, label: 'Nom' %>
<%= f.input :first_name, label: 'Prénom' %>
<%= f.input :number, label: 'Téléphone' %>
<%= f.input :email, label: 'Mail' %>
<%= f.input :address, label: 'Adresse' %>
<%= f.association :state, collection: State.order(:category), prompt: "Choisir un état" %>
<%= f.input :grade, label: 'Note', collection:[1, 2, 3, 4, 5] %>
<%= f.submit 'Créer le contact', class:'btn-modifications' %>
<% end %>
But I have a collection not with a list of "on-going", "called", "not-contacted" but I have a list with this:
State:0x00007fcb3afcfca8
How can I display the list I want?
You need to change it to below
<%= f.association :state, collection: State.order(:category), label_method: :category, value_method: :id,prompt: "Choisir un état" %>
In liquid templates this is achieved like so:
{{ product.metafields.book.author }}
Which returns the value of 'author' for it's key 'book'
I'm using Shopify API and Ruby on Rails and have successfully looped over each metafield for a given product:
In the controller:
#products = ShopifyAPI::Product.find(:all, :params => {:limit => 10})
In the view:
<% #products.metafields.each do |metafield| %>
<%= metafield.key %> : <%= metafield.value %>
<% end %>
This returns all of the metafields for a product, as expected. How do I return only those metafields matching a specific key i.e. 'book' from the example above?
# add metafield
product = ShopifyAPI::Product.find(product_id)
product.add_metafield(ShopifyAPI::Metafield.new({
:description => 'Author of book',
:namespace => 'book',
:key => 'author',
:value => 'Kurt Vonnegut',
:value_type => 'string'
}))
# retrieve metafield
author = ShopifyAPI::Metafield.find(:first,:params=>{:resource => "products", :resource_id => product.id, :namespace => "book", :key => "author"}).value
More info: http://www.shopify.com/technology/3032322-new-feature-metafields
This seems to do the trick:
<% product.metafields.each do |metafield| %>
<% if metafield.key == "book" %>
<%= metafield.key %>: <%= metafield.value %><br/>
<% end %>
<% end %>
or
<% product.metafields.each do |metafield| %>
<% if metafield.key.include?("book") %>
<%= metafield.key %>: <%= metafield.value %><br/>
<% else %>
<% end %>
This works:
ShopifyAPI::Metafield.find(:first,:params=>{:resource => "products", :resource_id => 94549954, :key => "book"})
ShopifyAPI::Metafield.find(:all,:params=>{:product_id => product.id, :key=> 'book'})
You can get all metafields for a product
#product = ShopifyAPI::Product.find(params[:id])
After that, you can get its metafields
#metafields = #product.metafields
Or if you need just a specific metafield for that product
#metafield = ShopifyAPI::Product::Metafield.find(:all, where: {"product_id = ? AND metafield.key = ?", product.id, "book"})
I am trying to make available to upload a multiple pictures with paperclip. I am following this tutorial: http://www.emersonlackey.com/article/paperclip-with-rails-3
Unfortunately I have error:
No handler found for "apple_mac-1280x800.jpg"
Asset.rb
class Asset < ActiveRecord::Base
belongs_to :post
has_attached_file :asset, :styles => { :small => "100x100", :original => '800x600>'}
end
Post.rb
class Post < ActiveRecord::Base
has_many :assets
accepts_nested_attributes_for :assets, :allow_destroy => true
end
Posts_controller.rb
def new
#post = Post.new
5.times { #post.assets.build }
respond_to do |format|
format.html # new.html.erb
format.json { render json: #post }
end
end
def edit
#post = Post.find(params[:id])
5.times { #post.assets.build }
end
#Post form
<% create_url = {:url=>{:action=>"create"}} if #post.new_record? %>
<% form_for #post, :html => {:multipart => true} do |t| %>
<p>
<%= t.label :title, 'Virsraksts:' %>
<%= t.text_field :title %>
</p>
<p>
<%= t.label :content, 'Teksts:' %>
<%= t.text_area :content, :class => "mceEditor"%>
</p>
<%= t.fields_for :assets do |asset_fields| %>
<% if asset_fields.object.new_record? %>
<p>
<%= asset_fields.file_field :asset %>
</p>
<% end %>
<% end %>
<%= t.submit %>
<% end %>
<%end%>
Problem solved by changing
<%= t.fields_for :assets do |asset_fields| %>
to
<%= f.fields_for :assets do |asset_fields| %>
But could someone explain why?
i have a nested form model
<%= simple_form_for(#product, :html => { :multipart => true }) do |f| %>
<%= f.input :name %>
#... and some other
<%= f.simple_fields_for :productgroups do |builder| %>
<%= render 'form_productgroup', { :f => builder } %>
<% end %>
<% end %>
## partial-level-1: form_productgroup
<%= f.input :extrapercentage %>
#... and some other
<%= f.simple_fields_for :productmaterials do |builder| %>
<%= render 'form_productmaterial', { :f => builder } %>
<% end %>
## partial-level-2: form_productmaterial
<%= f.input :price %>
#... and some other
=> everything fine serverside, but i need to add records via ajax because each productgroup or productmaterial belongs to a specific type
now the question:
how to create a controller action which returns the new material form?
This code returns an error that f is not existing:
def new_productgroup
#product = Product.find(params[:id])
#productgroup = Productgroup.new(:product_id => #product.id, :materialgroup_id => params[:materialgroup_id])
render "form_productgroup", { :f => ???? }
end
please help me!
I use accepts_nested_attributes_for in a model but my child form isn't saved in the database?
I am building a nested form almost in the same way as in episode 196 / 197 from Ryan Bates railscasts. I have a parent question form and as a child the answer form:
models/question.rb
class Question < ActiveRecord::Base
belongs_to :user
has_many :answers, :dependent => :destroy
accepts_nested_attributes_for :answers, :reject_if => lambda { |a| a[:text].blank? },
:allow_destroy => true
validates :content, :presence => true
end
models/answer.rb
class Answer < ActiveRecord::Base
belongs_to :question
belongs_to :user
end
controllers/questions_controller.rb
class QuestionsController < ApplicationController
before_filter :authenticate_user!
def index
setup_questions
end
def create
#question = Question.new(params[:question])
#this is to get every id_key from the user into the params of the answer
params[:question][:answers_attributes].keys.each {|key| params[:question][:answers_attributes][key][:user_id] = current_user.id }
#question.user_id = current_user.id
if #question.save
redirect_to questions_path, :notice => "Successfully created question."
else
setup_questions
render :index
end
end
def edit
#question = Question.find(params[:id])
end
def update
#question = Question.find(params[:id])
respond_to do |format|
if #question.update_attributes(params[:question])
format.html { redirect_to(#question, :notice => 'Question was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #question.errors, :status => :unprocessable_entity }
end
end
end
def show
#question = Question.find(params[:id])
end
def destroy
#question = Question.find(params[:id])
#authorize! :destroy, #question
#question.destroy
redirect_to questions_path, :notice => "Successfully deleted question: #{#question.content}."
end
private
def setup_questions
#questions = Question.all
#question ||= Question.new
#question.answers.build #to build the answers form
end
end
views/question/_form.html.erb
<%= form_for(#question) do |f| %>
<!-- =================== -->
<!-- = Error handeling = -->
<% if #question.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#question.errors.count, "error") %> prohibited this question from being saved:</h2>
<ul>
<% #question.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<!-- =================== -->
<!-- ================= -->
<!-- = Question form = -->
<div class="field">
<%= f.label :content, "Question" %><br />
<%= f.text_field :content, :placeholder => "type your question here.." %>
</div>
<!-- ====================== -->
<!-- = Nested Answer form = -->
<div class="answer-field">
<%= f.fields_for :answers do |builder| %>
<%= builder.label :content, "Possible answer" %><br />
<%= builder.text_field :content, :placeholder => "type an optional answer.." %>
<% end %>
</div>
<!-- ====================== -->
<div class="actions">
<%= f.submit %>
</div>
<!-- ================= -->
<% end %>
So now the big question... Why doesn't it save anything from the answer field to the database? I thought one create action at the parent (question) should be enough and that the "accepts_nested_attributes_for" should take care of it's child(s).
Regards,
Thijs
1 Remove this line from controller
params[:question][:answers_attributes].keys.each {|key| params[:question][:answers_attributes][key][:user_id] = current_user.id }
2 add this into your view
<!-- = Nested Answer form = -->
<div class="answer-field">
<%= f.fields_for :answers do |builder| %>
<% builder.object.user = current_user %>
<%= builder.label :content, "Possible answer" %><br />
<%= builder.text_field :content, :placeholder => "type an optional answer.." %>
<%= builder.hidden_field, :user_id %>
<% end %>
</div>
<!-- ====================== -->