Как настроить форму / POST в Rails? - PullRequest
1 голос
/ 05 марта 2011

Эй, ребята, это мучает меня всю неделю.Я новичок в Rails, поэтому, пожалуйста, будьте осторожны :)

Моя корневая проблема в том, что я пытаюсь написать сообщение form_for, которое будет использовать автозаполнение на входе, чтобы связать сообщение с Клиентом.База данных ищет client_id, а не текстовое имя.Поэтому я попробовал пользовательскую проверку, которая будет искать текстовое значение и заменять его идентификатором.Мой файл Post.rb имеет это:

class Post < ActiveRecord::Base
    belongs_to :client
    attr_accessor :client_name
    attr_accessible :client_name
    before_validation_on_create :validate_client

    def validate_client
        self.client_id = 1 # just a test
    end

    def client_exists(passed_name)
      return Client.where(:full_name => passed_name).first.blank?
    end
end

Но когда я делаю это, ни одна из переменных формы не передается.База данных получает все пустые записи, кроме client_id. Как мне это сделать?Почему мои переменные формы не передаются?Заранее большое спасибо.

Редактировать 1: добавлено определение создания из posts_controller.rb

def create
    @post = Post.new(params[:post])

    respond_to do |format|
      if @post.save
        format.html { 
            redirect_to(posts_url) # redirect_to(@post, :notice => 'Post was successfully created.')        
        }
        format.xml  { render :xml => @post, :status => :created, :location => @post }
        format.js
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @post.errors, :status => :unprocessable_entity }
      end
    end
  end

Редактировать 2: Благодаря @apneadiving я изменил attr_accesible для включения других атрибутов, и этопередает записи POST в базу данных.

attr_accessible :client_id, :time, :content, :client_name

Но когда я изменяю функцию validate_client для поиска client_id,

def validate_client
    passed_name = self.client_name

    if client_exists(passed_name)
        c = Client.where(:full_name => passed_name).first
        self.client_id = c.id
    else
        errors.add_to_base "Error"
    end
end

Это всегда дает мне эту ошибку:

Вызывается идентификатор дляnil, который по ошибке будет равен 4 - если вы действительно хотите идентификатор nil, используйте object_id

Edit 3: вот моя форма сообщения.Я не могу получить значение: client_name должным образом.

<%= form_for(@post) do |f| %>
  <%= render 'common/error_messages', :object => f.object %>
  <div class="field">
      <%= f.label :content %><br />
      <%= f.text_area :content, :size => "50x6" %>
    </div>
  <div class="field">
    <div class="sub-field">
      <%= f.label :client_name %><br />
      <%= f.text_field :client_name, :size => "26" %>
    </div>
    <div class="sub-field">
      <%= f.label :date %><br />
      <%= f.text_field(:time, :class => 'date', :size => "10", :value => Date.today.strftime('%m/%d/%Y')) %>
    </div>
    <div class="sub-field">
      <%= f.label :time %><br />
      <%= f.time_select :time %>
    </div>
  </div>

  <div class="actions clear">
    <%= f.submit %>
  </div>
<% end %>

Редактировать 4: решение. Я изо всех сил пытался получить: client_name, потому что мой текст был слишком далеко во вкладках(Первоначально я приватизировал эту функцию, а затем вынул слово «частный»).Модифицированная версия ответа @ apneadiving решила его для меня!

class Post < ActiveRecord::Base
    belongs_to :client
    attr_accessor :client_name
    validate :validate_client

    def validate_client
        passed_name = self.client_name

        unless client = Client.find_by_full_name(passed_name).blank?
          self.client_id = Client.find_by_full_name(passed_name).id
        else
          errors.add(:client_name, "'#{passed_name}' cannot be found.")
        end
    end

end

Ответы [ 2 ]

1 голос
/ 05 марта 2011

Остерегайтесь ваших attr_acessible:

, если вы установите один, вы должны установить все переменные, которые могут быть установлены с помощью параметров.В противном случае они защищены от mass assignment

РЕДАКТИРОВАТЬ 1:

кажется c.id ноль, что означает, что ваша функция client_exists не работает должным образом.Попробуйте следующее (не проверено):

def validate_client
  unless client = Client.find_by_full_name(client_name).nil?
    client_id = client.id
  else
    errors.add_to_base "Error"
  end
end
0 голосов
/ 05 марта 2011

Ваш код client_exists неверен, он возвращает true, если он не существует. Кроме того, поскольку ваши client_exists и validation повторно используют один и тот же запрос, я бы переписал его немного.

def validate_client
  passed_name = self.client_name

  existing_client = Client.where(:full_name => passed_name).first
  if existing_client
    self.client_id = existing_client.id
  else
    errors.add_to_base "Error"
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...