Question

Ok I am making a JQuery .post request to a server to insert some data. It only works sometimes depending on what methods are in the Rails create method.

Here are the specifics. I have a Rails app with Backbone.js on the frontend. In my frontend code I make this .post request

$.post('/publications');

Seems simple enough. I have a Publication model as well as

resources :publications

in the router. Now in my Publications controller I augmented the create method to the following:

  def create
    feed = Feedzirra::Feed.fetch_and_parse(publication_params[:url])
    params = {:name => feed.title}
    @publication = Publication.new(params)

    respond_to do |format|
      if @publication.save
        format.html { redirect_to @publication, notice: 'Publication was successfully created.' }
        format.json { render action: 'show', status: :created, location: @publication }
      else
        format.html { render action: 'new' }
        format.json { render json: @publication.errors, status: :unprocessable_entity }
      end
    end
  end

Feedzirra is a gem that parses RSS feeds. When I make the POST request like this I get a 500 (Internal Server Error) and this message from my server logs

NoMethodError (undefined method `title' for {}:Hash):
  app/controllers/publications_controller.rb:28:in `create'


  Rendered /Users/ericabt1/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/_source.erb (40.3ms)
  Rendered /Users/ericabt1/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.1ms)
  Rendered /Users/ericabt1/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (1.0ms)
  Rendered /Users/ericabt1/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (54.7ms)

What is confusing me is that if I choose a different method than 'title' like 'entries' or 'nil?' the POST request works just fine. I know that 'title' is indeed a method because when I go into Rails console and create a test Feedzirra object and look at the various methods available I see that 'title' is one of them.

Why does my POST request work for some of these method but not others?!?!?!?!

* UPDATE ****

After taking krabbi and Alexander Zolotko's advice I started playing with what FeedZirra is returning. It looks like the line

feed = Feedzirra::Feed.fetch_and_parse(publication_params[:url])

is returning an empty hash.

Now when I run the same line in the rails console and hardcode a url in there it returns the proper hash and I am able to grab the title and other values. So it looks like the issue lies with

publication_params[:url]

Still working on this and open to suggestions:)

* UPDATE PART TWO *

I thought the problem was that there was no url column in the Publication Model. So I made the proper migration. So here is the schema:

  create_table "publications", force: true do |t|
    t.string   "name"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "url"
  end

Back to the controller I have at the bottom:

 private
    # Use callbacks to share common setup or constraints between actions.
    def set_publication
      @publication = Publication.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def publication_params
       params.permit(:name, :url)
    end

publication_params[:url] is still returning nil. I have also tried the line:

params.require(:publication).permit(:url, :name)

which just gives me 400 Bad request error

Was it helpful?

Solution

As Alexander Zolotko points out Feedzirra::Feed.fetch_and_parse seems to return a hash.

Try for example

params = { :name => feed[:title] }

Assuming frontend is correct and REST resource publications is properly set up in Rails backend.

Controller should for example look like:

def create
  # requesting the feed from passed url
  feed = Feedzirra::Feed.fetch_and_parse(publication_params[:url])

  # mapping feed keys to publication attributes
  feed_to_publication_hash = { :name => feed[:title], anything else }

  # instantiating new publication
  @publication = Publication.new(publication_params.merge(feed_to_publication_hash))
  ...
end

private

def publication_params
  params.require(:publication).permit(:url, everything else you need)
end

I am quite sure that even if that works it is not good practice. Usually you strife for Object Orientation, that is in this case one purpose per action.

But I don't know right now how to refactor fetching the feed and perhaps mapping the hash. Maybe it is a controller concern or something like that.

OTHER TIPS

After reviewing the Feedzirra::Feed.fetch_and_parse the only option I see is that your publication_params[:url] contains something other than String. In that case fetch_and_parse returns a Hash of results (even if only one url was passed). Could you please check whether publication_params[:url].is_a?(String) is true.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top