Form_tag - formularz zapamiętujący dane

Witam, mój pierwszy post tutaj a więc oficjalne dobry wieczór wszystkim :wink:
Dopiero uczę się RoR, jakieś tam doświadczenie mam z Java Struts i może przez to trudno mi niektóre rzeczy zrozumieć w railsach. W każdym bądź razie w trakcie nauki z Agile Web D. with Rails nachodzą mnie różne pytania dodatkowe. Zazwyczaj przy pomocy google i własnej wiedzy udaje mi się je rozwiązać ale niekiedy jestem po prostu pewien, że rozwiązanie jest nieestetyczne. Do rzeczy, stworzyłem formularz bez powiązania z modelem, kontroler i dopisałem przekierowania w routes.rb.

[code]


<% if flash[:alert] %>

<%= flash[:alert] %>


<% end %>

<%= form_tag do %>

Please Log In

    <div>
      <label for="name">Name: </label>
      <%= text_field_tag :name, params[:name]%>
    </div>

    <div>
      <label for="password">Password:</label>
      <%= password_field_tag :password, params[:password] %>
    </div>

    <div>
      <%= submit_tag "Login" %>
    </div>

  </fieldset>

<% end %>

[/code] W momencie gdy wpiszę poprawny login i hasło przekierowuje mnie na inna stronę, gdy jednak będzie coś źle wracam do obecnej strony z komunikatem. Cały formularz czyści się, chciał bym jednak aby pamiętał poprzednie wartości. Rozwiązałem to tak [code]class SessionsController < ApplicationController

def new
params[:name] = flash[:name] if flash[:name]
end

def create
if user = User.authenticate(params[:name], params[:password])
session[:user_id] = user.id
redirect_to admin_url
else
flash[:name] = params[:name]
redirect_to login_url, :alert => “Invalid user/password”
end
end
end[/code]
l
Proszę o podpowiedź, czy istnieje lepsze/poprawne rozwiązanie takiego błahego problemu?

kiedy hasło jest nieprawidłowe, zamiast redirect_to lepiej po prostu wyrenderować widok akcji new:

render :new

Dokładnie jak poprzednik.

ja mam tak:

[code]
def login
if session[:id_admin]
redirect_to admin_index_home_path
end

Admin.validLogin
@auth = Admin.new(params[:admin])
if params[:admin]
  if @auth.valid?
    if admin = Admin.authenticate(params[:admin])
      session[:id_admin] = admin.id # Remember the user's id during this session 
      Admin::addInforationLogin session[:id_admin], remote_ip
      flash[:success] = 'Zalogowany poprawnie, witaj w systemie.'
      redirect_to admin_index_home_path
    else
      flash[:success] = 'Proszę podać prawidłowe dane do logowania.'
      render :action => 'login'
    end
  end
end

end[/code]

Dziekuje Panowie za szybki odzew. Teraz mam kolejny problem, ćwiczę sobie różnego rodzaju relacje i od wczoraj rana męczę się z relacją wiele do wielu. Poznałem już te dwa sposoby (3 modele + has_many,belongs_to oraz 2 modele + has_and_belongs_to_many), postanowiłem zrobić to drugim bo w tabeli ?krzyżowej? nie będę przechowywać żadnych danych oprócz kluczy obcych.
Wymyśliłem sobie bazę przechowującą produkty i kategorie, oczywiście każdy produkt może mieć wiele kategorii a kategoria należeć do wielu produktów. Fajnie by było aby przy dodawaniu nowego produktu mieć listę check box’ów wszystkich dostępnych kategorii i tam sobie wyklikać te do których zalicza sie nasz produkt. A więc tak stworzyłem migracje i modele, z poziomu konsoli rails’ow wszystko ładnie się zapisuję wiec tu raczej jest ok
to moje modele

[code]class Category < ActiveRecord::Base
has_and_belongs_to_many :products
#has_many :categories_products
#has_many :products, :through => :categories_products
attr_accessible :name, :rate
attr_accessor :check_box
attr_accessible :check_box # wirtualny atrybut
end

class Product < ActiveRecord::Base
has_and_belongs_to_many :categories
#has_many :categories_products
#has_many :categories, :through => :categories_products
attr_accessible :name, :categories
accepts_nested_attributes_for :categories
end

class CategoriesProduct < ActiveRecord::Base
belongs_to :product
belongs_to :category
end[/code]
są tam cześci zakomentowane ale jak już pisałem próbowalem dwiema metodami to zrobić
teraz jedyna ważna część kontrolera products_controller

[code] # GET /products/new

GET /products/new.json

def new
@product = Product.new
@categories2 = Category.all
categories = @product.categories.build()
respond_to do |format|
format.html # new.html.erb
format.json { render json: @product }
end
end

GET /products/1/edit

def edit
@product = Product.find(params[:id])
@categories2 = @product.categories
end[/code]
oraz istotna część widoku produktu _form

[code]<%= form_for(@product) do |f| %>

<%= f.label :name %>
<%= f.text_field :name %>
Dostepne kategorie:
<% @categories.each do |c|%> <%= f.fields_for @categories do |builder| %> <%= builder.check_box :check_box %> <%= builder.label :name %> <%= c.name %> <% end %>
<% end %>
<%= f.submit %>
<% end %>[/code] niestety wyświetla się w miejsce label Name. Subimt takiego forma powoduje że dostaje później obiekt Product składający się z jego pól plus tablicy tych atrybutów, z tymże każdy atrybut posiada tylko ten check_box, nei zawiera pól kategorii. Oglądałem już kilka screencastów między innymi [url=http://railscasts.com/episodes/196-nested-model-form-part-1?view=asciicast]#196 Nested model form part[/url] [url=http://railscasts.com/episodes/185-formtastic-part-2?view=asciicast]#185 formtastic-part2[/url] -ten doskonale opisuje mój kłopot ale jeszcze nie chce używać formastic ani simple_form [url=http://iqbalfarabi.net/2011/01/20/rails-nested-form-with-has-many-through-association/]Rails Nested Form with Has Many Through Association[/url] Już mam tak łeb zlasowany tym problem, a nie potrafię odpuścić i zająć się jakąś inną rzeczą. Z góry dziękuje za podpowiedź i pomoc

Najłatwiej byłoby właśnie z simple_form. No ale skoro nie chcesz.

[code]<%= form_for(@product) do |f| %>

<%= f.label :name %>
<%= f.text_field :name %>
Dostepne kategorie:
<% @categories.each do |category| %> <%= category.name %> <%= check_box_tag "product[category_ids][]", category.id, @product.category_ids.include?(category.id) %> <% end %>
<%= f.submit %>
<% end %>[/code] Gdzie: @categories = Category.all @product.category_ids - odwołuje się do Twojej relacji i zwraca tablicę id kategorii.

Oczywiście ładniej będzie, jeśli wyprowadzisz tę relację HABTM do partiala, przekazując mu tylko potrzebne parametry.

  • ewentualnie ustaw sobie @category_ids = @product.category_ids dla przejrzystości kodu

z jednej strony ciesze się szybkiej odpowiedzi z drugiej wściekły jestem, że wcześniej was nie spytałem :stuck_out_tongue: stracić na takiej rzeczy tyle czasu… w każdym bądź razie dziękuje za pomoc
Mówiąc żebym wyprowadził ta relację do partiala co masz na myśli?

<%= render 'form', :@categories => Category.all %>

takie coś chyba nie?
a co do simple_form to teraz się za to wezmę, chciałem tylko poznać mechanizmy railsów i nie rozwiązywać wszystkiego od razu gemami. Wtedy już w ogóle nie wiedział bym co się dzieje

Formularz jak formularz.

Tworzysz plik np _categoies.html.erb, do niego przerzucasz

Dostepne kategorie:<br> <% categories.each do |category| %> <label><%= category.name %> <%= check_box_tag "product[category_ids][]", category.id, product.category_ids.include?(category.id) %> </label> <% end %>
A w form wywolujesz

<%= render partial: 'categories', locals: { products: @products, categories: @categories } %>